@zvndev/darkmown 2.11.0 → 2.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -4
- package/CHANGELOG.md +15 -0
- package/README.md +10 -4
- package/docs/cli.md +1 -0
- package/docs/spec-alignment.md +10 -0
- package/package.json +1 -1
- package/site/pages/docs/index.wd +4 -4
- package/site/pages/playground/index.js +6 -8
- package/src/catalog.js +2 -0
- package/src/cli.js +14 -4
- package/src/compiler/markdown.js +14 -2
- package/src/compiler/page.js +12 -12
- package/src/font-subset.js +335 -105
- package/src/statics.js +171 -15
- package/types/font-subset.d.ts +54 -6
- package/types/statics.d.ts +42 -3
package/AGENTS.md
CHANGED
|
@@ -41,7 +41,7 @@ package.json
|
|
|
41
41
|
- Files/folders starting with `.`, `-`, or `_` are **hidden** from routing (drafts, partials).
|
|
42
42
|
- A `page.skin` next to `page.wd` attaches styling; a `page.js` attaches behavior. Matched by basename.
|
|
43
43
|
- **Colocated assets:** any other file under `site/pages/` (not a `.md`/`.wd` route, not a basename-matched `.skin`/`.js`) copies to `dist/` at its own path with the right content-type — so `site/pages/logo.svg` is served at `/logo.svg`. Use the `site/_/` shelf for assets shared across pages; colocate the ones a single page owns.
|
|
44
|
-
- **Responsive image variants:** with sharp installed (`npm i -D sharp`, an optional dependency; builds work without it), the build scans `site/pages` for raster photos (jpg/jpeg/png/webp) over 700px wide and writes resized `name@640.ext` / `name@1280.ext` variants into `dist`, wiring a `srcset` onto the Markdown image with the original kept as `src`. Only widths below the intrinsic size are generated (never upscale), variants keep the source format, and EXIF orientation is applied. **Author-provided `name@<width>.ext` exports win per width**: your file is copied verbatim and measured from its own header (a `@640` file holding 600px emits `600w`), and generation fills only the uncovered widths; other sizes are hand exports on the probe list (64, 96, 128, …, 3840). Skipped silently: images ≤700px, `@width` files, hidden/symlinked paths, svg/gif/avif, and shelf images (the generator covers page-colocated images only). Without sharp the build behaves as before plus one `npm i -D sharp` hint per build; a corrupt image or a sharp failure on one file is a hint naming the file, never a build failure. Resizes cache in `node_modules/.cache/darkmown-images/` (content hash + width + format), so rebuilds and dev reloads do zero sharp work for unchanged images. Never wired: bound srcs (``), remote/`data:`/query-hash srcs, page-relative or extensionless srcs, and raw-HTML `<img>` tags; `sizes`
|
|
44
|
+
- **Responsive image variants:** with sharp installed (`npm i -D sharp`, an optional dependency; builds work without it), the build scans `site/pages` for raster photos (jpg/jpeg/png/webp) over 700px wide and writes resized `name@640.ext` / `name@1280.ext` variants into `dist`, wiring a `srcset` onto the Markdown image with the original kept as `src`. Only widths below the intrinsic size are generated (never upscale), variants keep the source format, and EXIF orientation is applied. **Author-provided `name@<width>.ext` exports win per width**: your file is copied verbatim and measured from its own header (a `@640` file holding 600px emits `600w`), and generation fills only the uncovered widths; other sizes are hand exports on the probe list (64, 96, 128, …, 3840). Skipped silently: images ≤700px, `@width` files, hidden/symlinked paths, svg/gif/avif, and shelf images (the generator covers page-colocated images only). Without sharp the build behaves as before plus one `npm i -D sharp` hint per build; a corrupt image or a sharp failure on one file is a hint naming the file, never a build failure. Resizes cache in `node_modules/.cache/darkmown-images/` (content hash + width + format), so rebuilds and dev reloads do zero sharp work for unchanged images. Never wired: bound srcs (``), remote/`data:`/query-hash srcs, page-relative or extensionless srcs, and raw-HTML `<img>` tags; the build never invents a `sizes` value, but the author can set one on the Markdown image with `{sizes="(max-width: 640px) 100vw, 640px"}` (raw `<img srcset sizes>` on an `html: true` page remains the escape hatch). `.md` pages get the width/height/lazy hardening but no srcset. The first image on the page stays eager with `fetchpriority="high"`, the rest lazy-load, and author-set attributes always win.
|
|
45
45
|
- Shelf `.json` files publish to `/__wd/data/<name>`; every other shelf file publishes to `/__wd/media/<path>`. Hidden segments (`.`, `-`, `_`) and symlinks are never published, matching the page-asset rule; a symlink that stays inside `site/_/` still works as an `@include`/`@loop` source (it unrolls into pages at build time), it is just never copied to `dist`.
|
|
46
46
|
|
|
47
47
|
Commands: `darkmown dev`, `darkmown build [--drafts]`, `darkmown validate` (compile-check without writing `dist`), `darkmown serve` (previews `dist`, runs `api/` functions like dev, and compresses text responses), `darkmown deploy <vercel|cloudflare>`, `darkmown catalog [--llms|--llms-full]`, `darkmown mcp` (an MCP server on stdio: catalog, grammar, validate, error codes, docs).
|
|
@@ -73,7 +73,7 @@ rss_limit: 20
|
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
- `title`, `description`, `image` drive `<title>`, the meta description, and the Open Graph / Twitter card. `lang` sets `<html lang>` (default `en`).
|
|
76
|
-
- `html: true` allows raw HTML in that file's body. `transitions: true` opts into view
|
|
76
|
+
- `html: true` allows raw HTML in that file's body. `transitions: true` opts into a view transition (opacity-only, sequenced out-then-in) plus link prerendering.
|
|
77
77
|
- `draft: true` keeps the page out of `dist`, `routes.json`, the sitemap, and the feed. `darkmown dev` still serves it; `darkmown build --drafts` includes it.
|
|
78
78
|
- `noindex: true` builds the page but removes it from discovery: a robots `noindex,nofollow` meta, and exclusion from `sitemap.xml`, `rss.xml`, and the generated `llms.txt`/`llms-full.txt`. On a collection entry with a `_schema.wd`, declare it as `noindex: boolean?`.
|
|
79
79
|
- `icon: /path` sets the favicon verbatim (a `type` is added for `.svg`/`.png`/`.ico`). With no `icon:` key, the first of `site/pages/icon.svg`, `icon.png`, `favicon.ico` wins; with neither, the built-in mark is the fallback.
|
|
@@ -508,7 +508,7 @@ Your `.skin` selectors must match the **real** output. The emitted HTML is:
|
|
|
508
508
|
| reactive `@loop` of a list | `<ul>`/`<ol>` (or `<div>`) of items |
|
|
509
509
|
| `{ name }` | a text node |
|
|
510
510
|
|
|
511
|
-
So style with real selectors: `section`, `.card`, `button`, `input`, `form`, `h1`. **To add a class to a container, use `::: name .class`; to add one to a single inline element, use a trailing `{.class .class #id}`, as in `[Get started](/start/){.btn}`.** Inline attributes attach to **links, images, and emphasis** only; they do **not** work on inline code (`` `x` ``{.hl} renders the braces as text). A container class can also be reactive: `::: card .on-sale when p.price < 50` toggles the class from a predicate (same grammar as `:if`).
|
|
511
|
+
So style with real selectors: `section`, `.card`, `button`, `input`, `form`, `h1`. **To add a class to a container, use `::: name .class`; to add one to a single inline element, use a trailing `{.class .class #id}`, as in `[Get started](/start/){.btn}`.** Inline attributes attach to **links, images, and emphasis** only; they do **not** work on inline code (`` `x` ``{.hl} renders the braces as text). On an image the block also takes `sizes="…"` (`{sizes="(max-width: 640px) 100vw, 640px"}`), passed through HTML-escaped with or without a wired `srcset`. A container class can also be reactive: `::: card .on-sale when p.price < 50` toggles the class from a predicate (same grammar as `:if`).
|
|
512
512
|
|
|
513
513
|
Every heading also gets a stable GitHub-style `id` at build time, so `[jump](#my-heading)` deep-links with zero JS.
|
|
514
514
|
|
|
@@ -676,7 +676,7 @@ Raw TTFs are the most expensive asset a marketing site ships: in the measured re
|
|
|
676
676
|
1. **Let the build do it:** `npm i -D harfbuzzjs wawoff2` (both optional dependencies) and a post-pass subsets every project-local `.ttf`/`.otf`/`.woff` in an `@font-face src url(...)` to the site's charset (every code point in the emitted HTML, plus a base set of ASCII, Latin-1, punctuation, arrows, and ★ ✓ ✗), emits `<name>-subset.woff2` beside the original, and rewrites the dist CSS to list the subset first. Cached in `node_modules/.cache/darkmown-fonts/`, idempotent under dev rebuilds, and absent the toolchain you get one hint per build and unchanged output. Measured on the rebuild: 1.07 MB of TTFs became 288 KB of woff2.
|
|
677
677
|
2. Or do it by hand: convert to **woff2**, subset to the glyphs the site uses, and ship the result yourself.
|
|
678
678
|
|
|
679
|
-
Either way: serve fonts from the shelf (`site/_/fonts/`, published at `/__wd/media/fonts/`) or colocate them, declare them with `@font-face` in a shared skin, always
|
|
679
|
+
Either way: serve fonts from the shelf (`site/_/fonts/`, published at `/__wd/media/fonts/`) or colocate them, declare them with `@font-face` in a shared skin, and always set `font-display swap`. Preloading is automatic since 2.12: the build injects one `<link rel="preload" as="font" crossorigin>` per project font into every page whose own stylesheets declare it, leading with the subset woff2 when subsetting ran, so the first paint skips the fallback-font swap and reflow.
|
|
680
680
|
|
|
681
681
|
### Pre-fill a form message from query params
|
|
682
682
|
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Darkmown are documented here. Versions follow [semver](https://semver.org); pre-1.0 minor versions may contain breaking changes.
|
|
4
4
|
|
|
5
|
+
## 2.12.1 (2026-10-16)
|
|
6
|
+
|
|
7
|
+
A one-item patch revising the navigation animation again, this time from frame-level measurement instead of reading the stylesheet.
|
|
8
|
+
|
|
9
|
+
- **BEHAVIOR CHANGE: the default view transition is now a sequenced out-then-in.** The 2.12.0 simultaneous cross-fade was recorded with CDP screencast on the real demo and it double-exposes: the incoming snapshot stacks OVER the outgoing one, so the outgoing page stays fully visible while the incoming ghosts through it (a fade-in-only variant measured no better, since the old snapshot simply holds at full opacity for the whole window). The old root now fades to opacity 0 in 90ms and the new root fades in over 130ms after an 80ms delay, both opacity-only with the same easing and fill mode, so the overlap is about 10ms near background opacity and nothing ghosts. The reduced-motion block collapses both animations to 1ms with 0ms delay. Keyframe names, the `@view-transition` opt-in, and the prerender hint are unchanged, and a `transitions: true` page still ships zero JS.
|
|
10
|
+
|
|
11
|
+
## 2.12.0 (2026-10-16)
|
|
12
|
+
|
|
13
|
+
A perceived-performance release from client-demo feedback (fonts visibly swapped on every reload, and the navigation transition read as a flicker): fonts now preload, the preview server revalidates instead of re-downloading, the default view transition is a plain cross-fade, and Markdown images can carry an author-set `sizes`. No breaking change; the transition animation change is called out below.
|
|
14
|
+
|
|
15
|
+
- **Build-time font preloads.** The font post-pass gained a stage: after subsetting and the CSS rewrite, it injects one `<link rel="preload" as="font" crossorigin>` into every emitted page for each project font the page's own stylesheets declare, placed right after the last stylesheet link. The preloaded URL is exactly the one the rewritten CSS leads with (the `-subset.woff2` when subsetting ran, else the original project font, which still beats no preload), with `type` matching the extension and `crossorigin` always set, because font fetches are always CORS-mode and a preload without it downloads twice. Only fonts the page actually loads are preloaded (a page whose CSS declares no project fonts is byte-identical), remote `http(s)` srcs are never preloaded, already-`.woff2` project fonts are preloaded as-is, and the injection is idempotent, so incremental dev rebuilds never duplicate a link. The payoff is no fallback-font swap and reflow on first paint.
|
|
16
|
+
- **Conditional-request caching on `darkmown serve`.** Every static response (200s and the built 404) now sends `Last-Modified` and a strong `ETag`, and `If-None-Match` / `If-Modified-Since` are honored with body-less 304s (comma-lists and `*`, RFC 7232 precedence, validators repeated on the 304). Cache-Control by file class: HTML gets `no-cache` (always revalidate, cheaply), `/__wd/` assets and media/font extensions get `public, max-age=3600` (unchanged between builds, and any rebuild moves the validators), everything else stays deliberately unopinionated at `no-cache`. The freshness check runs before compression work and composes with the existing br/gzip negotiation; `api/` responses are untouched, and `darkmown dev` sends none of this by design. Reloads in the preview now revalidate instead of re-downloading every asset.
|
|
17
|
+
- **BEHAVIOR CHANGE: the default view transition is now a simultaneous cross-fade.** `transitions: true` used to emit paired directional animations (the old page slid up and out, the new one rose in), which on a real site read as a flicker: the outgoing page appeared to come back mid-navigation. Both animations are now opacity-only, 160ms with one shared easing both ways, so out and in run as one cross-fade rather than an out-then-in sequence. There is deliberately no `transform` anywhere in the stylesheet. The keyframe names (`wd-nav-out` / `wd-nav-in`) are unchanged, so author CSS referencing them still resolves; the `@view-transition` opt-in line, the reduced-motion reduction (1ms), and the speculation-rules prerender are unchanged; and a `transitions: true` page still ships zero JS.
|
|
18
|
+
- **Author-set `sizes` on Markdown images.** The inline-attribute block now accepts `sizes="…"` on images, in any order alongside `.class` and `#id`: `{sizes="(max-width: 640px) 100vw, 640px"}` passes the attribute through, HTML-escaped, whether or not the image has a wired `srcset` (with variants it rides alongside them). Without `sizes`, browsers default to `100vw` and fetch the full-size original on desktop, which made the 2.9 variant wiring dead weight there. The "the build never invents a sizes value" rule stands; on a link or emphasis the token is ignored; unrecognized blocks like `{foo="x"}` still render as literal text; and raw-HTML `<img>` remains author territory.
|
|
19
|
+
|
|
5
20
|
## 2.11.0 (2026-10-15)
|
|
6
21
|
|
|
7
22
|
A release for the agents reading the docs, not just the agents writing pages: the compiler and the whole language description are now one MCP server away, and any page can serve its own markdown source. No breaking change.
|
package/README.md
CHANGED
|
@@ -84,7 +84,7 @@ npm run dev # live demo site — the same site that runs darkmown.com
|
|
|
84
84
|
- `darkmown build [--target cloudflare] [--drafts]` writes static output to `dist` (plus `sitemap.xml`/`rss.xml`/`robots.txt`); `--drafts` includes `draft: true` pages for staging.
|
|
85
85
|
- `darkmown validate [path]` compile-checks `site/pages` (or one file or directory) against the real compiler without writing `dist`. Each page reports `compiles.` with its static/reactive status, warnings as bullets, or the coded error with its file, line, and fix hint; drafts are included and the exit code is 1 when any page fails, so it gates CI.
|
|
86
86
|
- `darkmown deploy <vercel|cloudflare> [--prod]` builds and deploys via the platform CLI.
|
|
87
|
-
- `darkmown serve` previews the built `dist` locally. It also runs the project's `api/` functions (same handler contract and routing as `darkmown dev` and the production hosts, so `:form action="/api/…"` posts and `:fetch … from "/api/…"` demos work in the preview), and it compresses text responses: brotli preferred, then gzip, negotiated off the request's `Accept-Encoding` with `Vary: Accept-Encoding` set. `darkmown dev` is deliberately uncompressed.
|
|
87
|
+
- `darkmown serve` previews the built `dist` locally. It also runs the project's `api/` functions (same handler contract and routing as `darkmown dev` and the production hosts, so `:form action="/api/…"` posts and `:fetch … from "/api/…"` demos work in the preview), and it compresses text responses: brotli preferred, then gzip, negotiated off the request's `Accept-Encoding` with `Vary: Accept-Encoding` set. Since 2.12 it also sends cache validators (`ETag`/`Last-Modified`) and honors conditional requests with 304s, so reloads revalidate instead of re-downloading every asset. `darkmown dev` is deliberately uncompressed and validator-free.
|
|
88
88
|
- `darkmown catalog [--llms|--llms-full]` prints the machine-readable directive catalog (JSON), a compact cheatsheet with `--llms`, or the complete reference including every error code with `--llms-full`. See [AI authoring](#ai-authoring).
|
|
89
89
|
- `darkmown mcp` runs a zero-dependency MCP server on stdio, exposing the catalog, grammar, validation, error codes, and docs as agent tools. See [MCP server](#mcp-server-darkmown-mcp).
|
|
90
90
|
- `darkmown version` prints the installed package version.
|
|
@@ -288,7 +288,7 @@ A few reserved keys drive **drafts and feeds** (see [SEO & feeds](#seo--feeds-si
|
|
|
288
288
|
|
|
289
289
|
**Markdown sources: `md_source: true`** on the home page opts the whole site in to publishing every page's byte-exact source beside its HTML: `/docs/` also answers `/docs.md` (the exact `.md`/`.wd` file the author wrote, frontmatter and CRLF endings included) with a `text/markdown` content type, and each published page carries `<link rel="alternate" type="text/markdown" href="/docs.md" title="Markdown source">`, emitted exactly when the file is, so the link never 404s. A page opts back out with `md_source: false`; a page-level `true` without the home flag does nothing, drafts never emit a source, and sitemap/rss/robots never list the `.md` files (they are alternates, not routes). Off by default, and a site that never sets it builds byte-identical output.
|
|
290
290
|
|
|
291
|
-
`transitions: true` opts a page into **instant, flash-free navigation
|
|
291
|
+
`transitions: true` opts a page into **instant, flash-free navigation**: zero JavaScript, all declarative. It emits a sequenced, opacity-only **view transition** for the page swap (the old page fades out in 90ms, the new page fades in over 130ms after an 80ms delay, one shared easing; the overlap is about 10ms near background opacity, so nothing ghosts or double-exposes), plus a **`<script type="speculationrules">` prerender** hint that renders the next same-origin page on hover/pointerdown so the click activates an already-painted page (no white render-gap flash). It honors `prefers-reduced-motion` (both animations collapse to 1ms with no delay). Only same-origin pages that both opt in transition; browsers without support, or with page-preloading disabled, navigate normally. Off by default; opt out with `transitions: false`. Mark a link `{.no-prefetch}` to exclude it from prerendering. (Chrome disables prerendering while DevTools is open, so test the built site with DevTools closed.)
|
|
292
292
|
|
|
293
293
|
## Static assets
|
|
294
294
|
|
|
@@ -315,7 +315,9 @@ Reference them with a normal URL: ``. The preview/`
|
|
|
315
315
|
- **Resizes are cached in `node_modules/.cache/darkmown-images/`**, keyed by content hash + width + format. A second build does zero sharp work for unchanged images and does not even load sharp when everything is cached (cached variants ship even if sharp is later removed). The cache lives under `node_modules`, which every project's `.gitignore` already excludes. Dev rebuilds recompute the variant map from the cache (no sharp spawn), so a partially rebuilt page is byte-identical to a full rebuild, srcset included; changing an image itself forces a full rebuild, which re-runs the pre-pass.
|
|
316
316
|
- The build summary reports the pre-pass when variants materialized: `Built 14 routes, sitemap (14 urls), rss (6 posts), image variants (2 generated, 5 cached) into dist`.
|
|
317
317
|
|
|
318
|
-
**Author-provided variants win (the `@width` convention).** Export `dr-aurora@640.jpg` yourself, same directory, same extension, and the build does not touch that width: your file is copied verbatim and measured from its own header (a `@640` file really holding 600px emits `600w`). Generation fills only the widths you did not provide, and the convention picks up any width on the compiler's fixed probe list (64, 96, 128, …, 3840), so other sizes are a hand export away; an off-list width like `x@500.webp` is a documented miss, never an error. Variant files (yours or generated) are ordinary colocated assets: they copy to `dist/` at their own path, and an `@`-suffixed filename is never a route. Everything else about the wiring is unchanged: descriptor widths are measured from file headers, candidates sort ascending with the original joining at its intrinsic width,
|
|
318
|
+
**Author-provided variants win (the `@width` convention).** Export `dr-aurora@640.jpg` yourself, same directory, same extension, and the build does not touch that width: your file is copied verbatim and measured from its own header (a `@640` file really holding 600px emits `600w`). Generation fills only the widths you did not provide, and the convention picks up any width on the compiler's fixed probe list (64, 96, 128, …, 3840), so other sizes are a hand export away; an off-list width like `x@500.webp` is a documented miss, never an error. Variant files (yours or generated) are ordinary colocated assets: they copy to `dist/` at their own path, and an `@`-suffixed filename is never a route. Everything else about the wiring is unchanged: descriptor widths are measured from file headers, candidates sort ascending with the original joining at its intrinsic width, and a page with no resizable images emits exactly what it did before.
|
|
319
|
+
|
|
320
|
+
The build still never invents a `sizes` value, but since 2.12 you can set one on the Markdown image itself with the inline-attribute block: `{sizes="(max-width: 640px) 100vw, 640px"}` passes `sizes` through onto the `<img>`, composing with `.class`/`#id` and with the wired `srcset`. Without `sizes`, browsers assume `100vw` and can fetch the full-size original on desktop, which makes the variants dead weight, so a hero image should carry one. Raw `<img srcset sizes>` on an `html: true` page remains the escape hatch (raw-HTML images are author territory: nothing is added or rewritten there).
|
|
319
321
|
|
|
320
322
|
**Never wired, by design:** a bound src (`` or a loop row's ``, which the runtime repaints), remote (`https://`, protocol-relative) and `data:` sources, srcs with a query/hash, page-relative or extensionless srcs, and raw-HTML `<img>` tags. **`.md` caveat:** variant wiring runs in the `.wd` compile path, so a plain `.md` page gets the width/height/lazy hardening but no srcset.
|
|
321
323
|
|
|
@@ -1261,7 +1263,9 @@ A trailing `{.class .class #id}` attaches classes / an id to the inline element
|
|
|
1261
1263
|
{.brand}
|
|
1262
1264
|
```
|
|
1263
1265
|
|
|
1264
|
-
The block must follow the element with no space, and works on links, images, and emphasis. It does **not** attach to inline code: `` `x` ``{.hl} leaves the braces in the output as literal text. It never collides with `{ name }` interpolation, because an interpolation always starts with a name, never a
|
|
1266
|
+
The block must follow the element with no space, and works on links, images, and emphasis. It does **not** attach to inline code: `` `x` ``{.hl} leaves the braces in the output as literal text. It never collides with `{ name }` interpolation, because an interpolation always starts with a name, never a `.`, `#`, or `sizes=`.
|
|
1267
|
+
|
|
1268
|
+
On an **image** the block also accepts `sizes="…"`, in any order alongside the classes and id, double-quoted and free to contain media conditions with spaces and commas: `{sizes="(max-width: 640px) 100vw, 640px"}` passes the attribute through, HTML-escaped, whether or not the image has a wired `srcset` (with variants it rides alongside them on the same `<img>`). That matters because a `srcset` without `sizes` makes browsers assume `100vw` and fetch the full-size original on desktop. On a link or emphasis target a `sizes` token is ignored, and a block that matches nothing recognized (like `{foo="x"}`) still renders as literal text.
|
|
1265
1269
|
|
|
1266
1270
|
**Headings get anchors for free.** Every markdown heading carries a stable, GitHub-style slug `id` at build time (lowercased, punctuation stripped, whitespace → hyphens; duplicates dedupe with `-1`/`-2` suffixes across the whole document), so any section of any page is deep-linkable with a plain `#the-slug` fragment — zero JS. The [docs page's](https://darkmown.com/docs/) "On this page" table of contents is just markdown links to those anchors.
|
|
1267
1271
|
|
|
@@ -1442,6 +1446,8 @@ Both are optional dependencies, lazily loaded in a child process behind the same
|
|
|
1442
1446
|
- **Cache:** `node_modules/.cache/darkmown-fonts/<fontHash>-<charsetHash>.woff2`, so a second build with unchanged fonts and content does zero wasm work and needs no toolchain for cached entries. The CSS rewrite is idempotent, which is what makes incremental dev builds safe.
|
|
1443
1447
|
- The build summary gains a `fonts (3 subsetted, 0 cached)` clause when the post-pass did work. Measured on a 67-route marketing rebuild: three variable TTFs totaling 1.07 MB became 288 KB of subset woff2 (a 3.7x reduction), first build about 9.6 s, cached rebuilds about 1.0 s.
|
|
1444
1448
|
|
|
1449
|
+
**Font preloads are injected automatically.** The same post-pass adds one `<link rel="preload" as="font" crossorigin>` per project font to every emitted page, right after the last stylesheet link, mapped per page from the fonts the page's own stylesheets declare (a page whose CSS declares no project fonts is byte-identical). The preloaded URL is exactly the one the rewritten CSS leads with: the `-subset.woff2` when subsetting ran, else the original project font (preloading the unsubsetted original still beats no preload), with `type` matching the extension. `crossorigin` is mandatory because font fetches are always CORS-mode; without it the browser downloads the font twice. Remote `http(s)` srcs are never preloaded, already-`.woff2` project fonts are preloaded as-is, and the injection is idempotent, so incremental dev rebuilds never duplicate a link. The payoff: no fallback-font swap and reflow on first paint.
|
|
1450
|
+
|
|
1445
1451
|
## The escape hatch
|
|
1446
1452
|
|
|
1447
1453
|
Reactive pages expose `window.wd` so a colocated `.js` file can do anything the directives deliberately don't — keyboard, drag/touch, canvas, charts, maps:
|
package/docs/cli.md
CHANGED
|
@@ -114,6 +114,7 @@ Since 2.8 the preview is at parity with dev for two things:
|
|
|
114
114
|
|
|
115
115
|
- **`api/` functions run.** A request to `/api/*` that matches a handler under the project's top-level `api/` directory executes it (same contract and file routing as `darkmown dev` and the production hosts: `api/echo.js` → `/api/echo`, `api/users/[id].js` → `/api/users/:id`); anything else falls through to static serving. `:form action="/api/…"` posts and `:fetch … from "/api/…"` demos that worked in dev now work in the preview too, and editing a handler is picked up without a restart. A project with no `api/` directory behaves exactly as before. Since 2.10.1 the local runner matches production hygiene: request bodies are capped at 10 MB (`413` over cap), a malformed percent-encoded dynamic segment answers `400`, and under `serve` a throwing handler answers the generic `{"ok": false, "error": "Internal error"}` while the real error is logged server-side only. `darkmown dev` keeps the verbose message, because in dev the developer is the audience.
|
|
116
116
|
- **Text responses are compressed.** The server negotiates off the request's `Accept-Encoding` (brotli preferred, then gzip, q-values honored) and sets `Vary: Accept-Encoding`, appending to an existing `Vary` rather than clobbering it. Compressible: `text/*`, `application/javascript`, `application/json`, `application/xml`, and `image/svg+xml`, across static files, the built 404 page, and `api/` responses (a handler that set its own `Content-Encoding` is never double-compressed). Images, video, audio, and fonts are never compressed. `darkmown dev` is intentionally uncompressed, byte-identical to 2.7.
|
|
117
|
+
- **Static responses carry cache validators.** Every static 200 (and the built 404) sends `Last-Modified` and a strong `ETag`; `If-None-Match` (comma-lists and `*` honored) and `If-Modified-Since` are answered with a 304 carrying the validators and no body, with `If-None-Match` taking precedence per RFC 7232. Cache-Control by file class: HTML gets `no-cache` (always revalidate, but revalidations are cheap 304s), anything under `/__wd/` and media/font extensions anywhere get `public, max-age=3600` (unchanged between builds, and any rebuild moves the validators), and everything else stays deliberately unopinionated at `no-cache`. The freshness check runs before compression work, and `api/` responses are untouched. Reloads therefore revalidate instead of re-downloading every asset. `darkmown dev` sends none of this, by design.
|
|
117
118
|
|
|
118
119
|
### `darkmown catalog [--llms|--llms-full]`
|
|
119
120
|
|
package/docs/spec-alignment.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
This audit compares the current Darkmown implementation with the original MARROW/WhateverDown vision and the follow-up decisions made on 2026-06-11.
|
|
4
4
|
|
|
5
|
+
## 2.12.1 additions: the transition, measured frame by frame (2026-10-16)
|
|
6
|
+
|
|
7
|
+
- **The navigation animation is now a sequenced out-then-in, because the cross-fade double-exposed on camera.** CDP screencast of the 2.12.0 simultaneous fade showed the incoming snapshot stacking over the outgoing one, ghosting the old page through the new; fading out first (90ms) and delaying the fade-in (130ms after 80ms) leaves only a ~10ms overlap near background opacity. Both animations stay opacity-only with shared easing, keyframe names are unchanged, and reduced motion still collapses the effect to 1ms.
|
|
8
|
+
|
|
9
|
+
## 2.12.0 additions: perceived performance from demo feedback (2026-10-16)
|
|
10
|
+
|
|
11
|
+
- **First paint stops swapping fonts.** The font post-pass now injects per-page `<link rel="preload" as="font" crossorigin>` tags for exactly the project fonts a page's own stylesheets declare, leading with the subset woff2 when subsetting ran (the original otherwise, still a win), idempotently so dev rebuilds never duplicate a link. `darkmown serve` learned conditional requests: strong ETags and Last-Modified on every static response, RFC 7232-correct 304s, HTML at `no-cache`, fingerprinted-by-build assets at `public, max-age=3600`, dev deliberately unchanged. Together these close the demo's "fonts swap on every reload" complaint from both ends: first load preloads, reloads revalidate.
|
|
12
|
+
- **The default navigation animation lost its flicker.** `transitions: true` now emits a simultaneous, opacity-only 160ms cross-fade both ways (no `transform` anywhere; the directional translate was the flicker source), with keyframe names, the reduced-motion reduction, and the prerender hint unchanged. It is a visible behavior change with no markup or config delta, and pages still ship zero JS.
|
|
13
|
+
- **The srcset story is complete: authors can set `sizes`.** The 2.9 variant wiring emitted no `sizes`, so browsers assumed `100vw` and fetched the full-size original on desktop. The inline-attribute block now passes `sizes="…"` through on Markdown images (the build still never invents one), composing with classes, ids, and the wired srcset.
|
|
14
|
+
|
|
5
15
|
## 2.11.0 additions: the framework speaks MCP, and every page speaks markdown (2026-10-15)
|
|
6
16
|
|
|
7
17
|
- **The language description became a protocol surface.** `darkmown mcp` is a hand-rolled, zero-dependency MCP stdio server (newline-delimited JSON-RPC 2.0, protocol 2024-11-05, no SDK, so `dependencies` stays empty). Its five tools (catalog, grammar, in-memory validate, error-code lookup, doc-section search) are thin adapters over the same drift-guarded surfaces the CLI and the test suite already pin, so an agent editing `.wd` through MCP gets the same answers as `darkmown validate`, with the shipped markdown docs riding along as `darkmown://docs/*` resources. That resource surface is why `docs/errors.md` now ships in the tarball.
|
package/package.json
CHANGED
package/site/pages/docs/index.wd
CHANGED
|
@@ -475,13 +475,13 @@ Mark a page `draft: true` and it stays out of production: `darkmown build` leave
|
|
|
475
475
|
|
|
476
476
|
## Instant navigation
|
|
477
477
|
|
|
478
|
-
Add `transitions: true` to a page's frontmatter for **instant, flash-free navigation
|
|
478
|
+
Add `transitions: true` to a page's frontmatter for **instant, flash-free navigation**: zero JavaScript. It emits a sequenced, opacity-only view transition for the page swap (the old page fades out in 90ms, the new page fades in over 130ms after an 80ms delay, one shared easing; the ~10ms overlap sits near background opacity, so nothing ghosts) and a `<script type="speculationrules">` prerender hint, so the browser renders the next same-origin page on hover/pointerdown and the click activates an already-painted page (no white render-gap). It honors `prefers-reduced-motion` (both animations collapse to 1ms with no delay), and only same-origin pages that both opt in transition. Off by default; opt out with `transitions: false`, or exclude a single link from prerendering with `{.no-prefetch}`. (Chrome turns prerendering off while DevTools is open, so test the built site with DevTools closed.)
|
|
479
479
|
|
|
480
480
|
## Images
|
|
481
481
|
|
|
482
482
|
You don't size images by hand. Every `<img>` the compiler emits gets its intrinsic `width`/`height` read from the source file (so the page doesn't reflow as images decode), `decoding="async"`, and a priority split — the first image stays eager with `fetchpriority="high"`, the rest `loading="lazy"`. Anything you set yourself wins. The compiler measures, it doesn't resize, so keep source images web-sized.
|
|
483
483
|
|
|
484
|
-
**Responsive variants, generated at build time.** With sharp installed (`npm i -D sharp`, an optional dependency; builds work without it), every raster photo in `site/pages` over 700px wide is resized to 640w and 1280w siblings in `dist/` (only widths below the intrinsic size, never upscaled, EXIF orientation applied), and the Markdown image gains a `srcset` with the original kept as `src`. Export `name@<width>.ext` yourself and your file wins that width verbatim, measured from its own header; generation fills only the widths you left uncovered, and other sizes are a hand export away (the compiler probes 64 through 3840). Skipped silently: small images, `@width` files, hidden or symlinked paths, svg/gif/avif, and shelf images (the generator covers page-colocated images only). Without sharp the build behaves as before plus one `npm i -D sharp` hint per build; a corrupt image or a sharp failure on one file is a hint naming the file, never a build failure. Resizes are cached in `node_modules/.cache/darkmown-images/` by content hash + width + format, so second builds and dev rebuilds do no resizing for unchanged images, and the build summary reports `image variants (N generated, M cached)` when variants materialized. `sizes`
|
|
484
|
+
**Responsive variants, generated at build time.** With sharp installed (`npm i -D sharp`, an optional dependency; builds work without it), every raster photo in `site/pages` over 700px wide is resized to 640w and 1280w siblings in `dist/` (only widths below the intrinsic size, never upscaled, EXIF orientation applied), and the Markdown image gains a `srcset` with the original kept as `src`. Export `name@<width>.ext` yourself and your file wins that width verbatim, measured from its own header; generation fills only the widths you left uncovered, and other sizes are a hand export away (the compiler probes 64 through 3840). Skipped silently: small images, `@width` files, hidden or symlinked paths, svg/gif/avif, and shelf images (the generator covers page-colocated images only). Without sharp the build behaves as before plus one `npm i -D sharp` hint per build; a corrupt image or a sharp failure on one file is a hint naming the file, never a build failure. Resizes are cached in `node_modules/.cache/darkmown-images/` by content hash + width + format, so second builds and dev rebuilds do no resizing for unchanged images, and the build summary reports `image variants (N generated, M cached)` when variants materialized. The build never invents a `sizes` value, but you can set one on the Markdown image itself: `{sizes="(max-width: 640px) 100vw, 640px"}` passes it through onto the `<img>`, composing with the wired `srcset` (raw `<img srcset sizes>` on an `html: true` page remains the escape hatch). Bound (``), remote, `data:`, query/hash, page-relative, and extensionless srcs are never wired, and neither are raw-HTML `<img>` tags. A `.md` page gets the hardening but no srcset.
|
|
485
485
|
|
|
486
486
|
## Static assets
|
|
487
487
|
|
|
@@ -901,7 +901,7 @@ Two CSS at-rules compile as self-contained blocks in a `.skin`, because their in
|
|
|
901
901
|
|
|
902
902
|
`@font-face` takes plain declarations, several blocks per skin allowed. `@keyframes <name>` requires a plain identifier; each indented child is a keyframe selector (`from`, `to`, a percentage, or a comma list) with its declarations one level deeper, and anything else is a compile error, so a keyframe selector is never misread as a declaration. Aliases and `$token` refs work inside both, both can nest under an `@media` line (the home for `prefers-reduced-motion` animation guards), and both stay **global** in a `scoped` skin, same as `tokens` blocks.
|
|
903
903
|
|
|
904
|
-
**Build-time font subsetting.** With the wasm toolchain installed (`npm i -D harfbuzzjs wawoff2`, both optional dependencies), a post-pass subsets every project-local `.ttf`/`.otf`/`.woff` referenced by an `@font-face src url(...)` to the site's character set (every code point in the emitted HTML, plus a base set of ASCII, Latin-1, punctuation, arrows, and ★ ☆ ✓ ✕ ✗), encodes it as woff2, emits `<name>-subset.woff2` beside the original, and rewrites the dist CSS so `src:` lists the subset first; the source `.skin` is never touched, and layout features and variable axes survive. Without the toolchain the build is unchanged plus one hint per build, a font that fails to parse ships as-is with its own hint, and the build never fails over a font. Subsets cache in `node_modules/.cache/darkmown-fonts/` keyed by font and charset hashes, and the CSS rewrite is idempotent, so incremental dev builds are safe. The build summary reports `fonts (3 subsetted, 0 cached)` when the post-pass did work.
|
|
904
|
+
**Build-time font subsetting.** With the wasm toolchain installed (`npm i -D harfbuzzjs wawoff2`, both optional dependencies), a post-pass subsets every project-local `.ttf`/`.otf`/`.woff` referenced by an `@font-face src url(...)` to the site's character set (every code point in the emitted HTML, plus a base set of ASCII, Latin-1, punctuation, arrows, and ★ ☆ ✓ ✕ ✗), encodes it as woff2, emits `<name>-subset.woff2` beside the original, and rewrites the dist CSS so `src:` lists the subset first; the source `.skin` is never touched, and layout features and variable axes survive. Without the toolchain the build is unchanged plus one hint per build, a font that fails to parse ships as-is with its own hint, and the build never fails over a font. Subsets cache in `node_modules/.cache/darkmown-fonts/` keyed by font and charset hashes, and the CSS rewrite is idempotent, so incremental dev builds are safe. The build summary reports `fonts (3 subsetted, 0 cached)` when the post-pass did work. The same pass also injects one `<link rel="preload" as="font" crossorigin>` per project font into every page whose own stylesheets declare it (leading with the subset woff2 when subsetting ran, else the original), so first paint skips the fallback-font swap.
|
|
905
905
|
|
|
906
906
|
## Inline attributes
|
|
907
907
|
|
|
@@ -911,7 +911,7 @@ A trailing `{.class .class #id}` attaches classes or an id to the inline element
|
|
|
911
911
|
[Get started](/start/){.btn .lg}
|
|
912
912
|
```
|
|
913
913
|
|
|
914
|
-
The block must follow the element with no space. It works on links, images, and emphasis, and it does **not** attach to inline code. It never collides with `{ name }` interpolation, because an interpolation always starts with a name, never a
|
|
914
|
+
The block must follow the element with no space. It works on links, images, and emphasis, and it does **not** attach to inline code. It never collides with `{ name }` interpolation, because an interpolation always starts with a name, never a `.`, `#`, or `sizes=`. On an image the block also accepts `sizes="…"` (double-quoted, media conditions with spaces and commas fine), passed through HTML-escaped alongside the classes and id, with or without a wired `srcset`; on a link or emphasis the token is ignored. This page uses it: a link marked `{.no-prefetch}` is excluded from the `transitions: true` prerender hint.
|
|
915
915
|
|
|
916
916
|
**Consecutive raw-HTML lines collapse into one paragraph.** On an `html: true` page, a run of lines that each start with an inline-level or unknown tag (`<a class="card">`, `<picture>`, a custom element) parses as ONE paragraph, so the elements render inline inside a single `<p>` instead of as layout siblings; a card grid collapses to one column this way. Lines starting with a block-level tag (`<div>`, `<section>`, …) never hit this, because CommonMark hoists them into an HTML block. The compiler warns once per run when 2+ consecutive lines of one paragraph each open with a component-looking tag (one carrying a `class` or `id`; classless prose links stay quiet):
|
|
917
917
|
|
|
@@ -31,7 +31,7 @@ https://github.com/highlightjs/highlight.js/issues/2277`),W=k,L=C),T===void 0&&(
|
|
|
31
31
|
`),t=t.replace(Gf,"\uFFFD"),e.src=t}function Qr(e){let t;e.inlineMode?(t=new e.Token("inline","",0),t.content=e.src,t.map=[0,1],t.children=[],e.tokens.push(t)):e.md.block.parse(e.src,e.md,e.env,e.tokens)}function eo(e){let t=e.tokens;for(let n=0,r=t.length;n<r;n++){let o=t[n];o.type==="inline"&&e.md.inline.parse(o.content,e.md,e.env,o.children)}}function Zf(e){return/^<a[>\s]/i.test(e)}function Kf(e){return/^<\/a\s*>/i.test(e)}function to(e){let t=e.tokens;if(e.md.options.linkify)for(let n=0,r=t.length;n<r;n++){if(t[n].type!=="inline"||!e.md.linkify.pretest(t[n].content))continue;let o=t[n].children,i=[],a=0;for(let u=o.length-1;u>=0;u--){let s=o[u];if(s.type==="link_close"){for(u--;o[u].level!==s.level&&o[u].type!=="link_open";)u--;continue}if(s.type==="html_inline"&&(Zf(s.content)&&a>0&&a--,Kf(s.content)&&a++),!(a>0)&&s.type==="text"&&e.md.linkify.test(s.content)){let c=s.content,l=e.md.linkify.match(c),d=[],f=s.level,m=0;l.length>0&&l[0].index===0&&u>0&&o[u-1].type==="text_special"&&(l=l.slice(1));for(let p=0;p<l.length;p++){let h=l[p].url,b=e.md.normalizeLink(h);if(!e.md.validateLink(b))continue;let E=l[p].text;l[p].schema?l[p].schema==="mailto:"&&!/^mailto:/i.test(E)?E=e.md.normalizeLinkText("mailto:"+E).replace(/^mailto:/,""):E=e.md.normalizeLinkText(E):E=e.md.normalizeLinkText("http://"+E).replace(/^http:\/\//,"");let g=l[p].index;if(g>m){let v=new e.Token("text","",0);v.content=c.slice(m,g),v.level=f,d.push(v)}let y=new e.Token("link_open","a",1);y.attrs=[["href",b]],y.level=f++,y.markup="linkify",y.info="auto",d.push(y);let x=new e.Token("text","",0);x.content=E,x.level=f,d.push(x);let A=new e.Token("link_close","a",-1);A.level=--f,A.markup="linkify",A.info="auto",d.push(A),m=l[p].lastIndex}if(m<c.length){let p=new e.Token("text","",0);p.content=c.slice(m),p.level=f,d.push(p)}i.push({index:u,nodes:d})}}if(i.length>0){let u=o.length;for(let d of i)u+=d.nodes.length-1;let s=new Array(u),c=0,l=0;i.reverse();for(let d=0;d<o.length;d++){let f=i[c];if(f?.index===d){for(let m of f.nodes)s[l++]=m;c++}else s[l++]=o[d]}t[n].children=s}}}var ks=/\+-|\.\.|\?\?\?\?|!!!!|,,|--/,jf=/\((c|tm|r)\)/i,Vf=/\((c|tm|r)\)/ig,Yf={c:"\xA9",r:"\xAE",tm:"\u2122"};function Xf(e,t){return Yf[t.toLowerCase()]}function Jf(e){let t=0;for(let n=e.length-1;n>=0;n--){let r=e[n];r.type==="text"&&!t&&(r.content=r.content.replace(Vf,Xf)),r.type==="link_open"&&r.info==="auto"&&t--,r.type==="link_close"&&r.info==="auto"&&t++}}function Qf(e){let t=0;for(let n=e.length-1;n>=0;n--){let r=e[n];r.type==="text"&&!t&&ks.test(r.content)&&(r.content=r.content.replace(/\+-/g,"\xB1").replace(/\.{2,}/g,"\u2026").replace(/([?!])…/g,"$1..").replace(/([?!]){4,}/g,"$1$1$1").replace(/,{2,}/g,",").replace(/(^|[^-])---(?=[^-]|$)/mg,"$1\u2014").replace(/(^|\s)--(?=\s|$)/mg,"$1\u2013").replace(/(^|[^-\s])--(?=[^-\s]|$)/mg,"$1\u2013")),r.type==="link_open"&&r.info==="auto"&&t--,r.type==="link_close"&&r.info==="auto"&&t++}}function no(e){let t;if(e.md.options.typographer)for(t=e.tokens.length-1;t>=0;t--)e.tokens[t].type==="inline"&&(jf.test(e.tokens[t].content)&&Jf(e.tokens[t].children),ks.test(e.tokens[t].content)&&Qf(e.tokens[t].children))}var ep=/['"]/,As=/['"]/g,xs="\u2019",tp=1e3;function vs(e,t,n){for(;e.length>n;){let r=e.pop();r.isSingleQuote?t.single=r.prevSameQuoteIdx:t.double=r.prevSameQuoteIdx}}function Nn(e,t,n,r){e[t]||(e[t]=[]),e[t].push({pos:n,ch:r})}function np(e,t){let n="",r=0;t.sort((o,i)=>o.pos-i.pos);for(let o=0;o<t.length;o++){let i=t[o];n+=e.slice(r,i.pos)+i.ch,r=i.pos+1}return n+e.slice(r)}function rp(e,t){let n,r=[],o={single:-1,double:-1},i={};for(let a=0;a<e.length;a++){let u=e[a],s=e[a].level;for(n=r.length-1;n>=0&&!(r[n].level<=s);n--);if(vs(r,o,n+1),u.type!=="text")continue;let c=u.content,l=0,d=c.length;e:for(;l<d;){As.lastIndex=l;let f=As.exec(c);if(!f)break;let m=!0,p=!0;l=f.index+1;let h=f[0]==="'",b=32;if(f.index-1>=0)b=c.charCodeAt(f.index-1);else for(n=a-1;n>=0&&!(e[n].type==="softbreak"||e[n].type==="hardbreak");n--)if(e[n].content){b=e[n].content.charCodeAt(e[n].content.length-1);break}let E=32;if(l<d)E=c.charCodeAt(l);else for(n=a+1;n<e.length&&!(e[n].type==="softbreak"||e[n].type==="hardbreak");n++)if(e[n].content){E=e[n].content.charCodeAt(0);break}let g=Qe(b)||Je(b),y=Qe(E)||Je(E),x=Xe(b),A=Xe(E);if(A?m=!1:y&&(x||g||(m=!1)),x?p=!1:g&&(A||y||(p=!1)),E===34&&f[0]==='"'&&b>=48&&b<=57&&(p=m=!1),m&&p&&(m=g,p=y),!m&&!p){h&&Nn(i,a,f.index,xs);continue}if(p&&(n=h?o.single:o.double,n>=0&&r[n].level===s)){let v=r[n],N,R;h?(N=t.md.options.quotes[2],R=t.md.options.quotes[3]):(N=t.md.options.quotes[0],R=t.md.options.quotes[1]),Nn(i,a,f.index,R),Nn(i,v.tokenIdx,v.contentPos,N),vs(r,o,n);continue e}if(m){if(r.length>=tp)return;r.push({tokenIdx:a,contentPos:f.index,isSingleQuote:h,level:s,prevSameQuoteIdx:h?o.single:o.double}),h?o.single=r.length-1:o.double=r.length-1}else p&&h&&Nn(i,a,f.index,xs)}}Object.keys(i).forEach(function(a){e[a].content=np(e[a].content,i[a])})}function ro(e){if(e.md.options.typographer)for(let t=e.tokens.length-1;t>=0;t--)e.tokens[t].type!=="inline"||!ep.test(e.tokens[t].content)||rp(e.tokens[t].children,e)}function oo(e){let t,n,r=e.tokens,o=r.length;for(let i=0;i<o;i++){if(r[i].type!=="inline")continue;let a=r[i].children,u=a.length;for(t=0;t<u;t++)a[t].type==="text_special"&&(a[t].type="text");for(t=n=0;t<u;t++)a[t].type==="text"&&t+1<u&&a[t+1].type==="text"?a[t+1].content=a[t].content+a[t+1].content:(t!==n&&(a[n]=a[t]),n++);t!==n&&(a.length=n)}}var io=[["normalize",Jr],["block",Qr],["inline",eo],["linkify",to],["replacements",no],["smartquotes",ro],["text_join",oo]];function ao(){this.ruler=new nt;for(let e=0;e<io.length;e++)this.ruler.push(io[e][0],io[e][1])}ao.prototype.process=function(e){let t=this.ruler.getRules("");for(let n=0,r=t.length;n<r;n++)t[n](e)};ao.prototype.State=ws;var Ss=ao;function Se(e,t,n,r){this.src=e,this.md=t,this.env=n,this.tokens=r,this.bMarks=[],this.eMarks=[],this.tShift=[],this.sCount=[],this.bsCount=[],this.blkIndent=0,this.line=0,this.lineMax=0,this.tight=!1,this.ddIndent=-1,this.listIndent=-1,this.parentType="root",this.level=0;let o=this.src;for(let i=0,a=0,u=0,s=0,c=o.length,l=!1;a<c;a++){let d=o.charCodeAt(a);if(!l)if(z(d)){u++,d===9?s+=4-s%4:s++;continue}else l=!0;(d===10||a===c-1)&&(d!==10&&a++,this.bMarks.push(i),this.eMarks.push(a),this.tShift.push(u),this.sCount.push(s),this.bsCount.push(0),l=!1,u=0,s=0,i=a+1)}this.bMarks.push(o.length),this.eMarks.push(o.length),this.tShift.push(0),this.sCount.push(0),this.bsCount.push(0),this.lineMax=this.bMarks.length-1}Se.prototype.push=function(e,t,n){let r=new Me(e,t,n);return r.block=!0,n<0&&this.level--,r.level=this.level,n>0&&this.level++,this.tokens.push(r),r};Se.prototype.isEmpty=function(t){return this.bMarks[t]+this.tShift[t]>=this.eMarks[t]};Se.prototype.skipEmptyLines=function(t){for(let n=this.lineMax;t<n&&!(this.bMarks[t]+this.tShift[t]<this.eMarks[t]);t++);return t};Se.prototype.skipSpaces=function(t){for(let n=this.src.length;t<n;t++){let r=this.src.charCodeAt(t);if(!z(r))break}return t};Se.prototype.skipSpacesBack=function(t,n){if(t<=n)return t;for(;t>n;)if(!z(this.src.charCodeAt(--t)))return t+1;return t};Se.prototype.skipChars=function(t,n){for(let r=this.src.length;t<r&&this.src.charCodeAt(t)===n;t++);return t};Se.prototype.skipCharsBack=function(t,n,r){if(t<=r)return t;for(;t>r;)if(n!==this.src.charCodeAt(--t))return t+1;return t};Se.prototype.getLines=function(t,n,r,o){if(t>=n)return"";let i=new Array(n-t);for(let a=0,u=t;u<n;u++,a++){let s=0,c=this.bMarks[u],l=c,d;for(u+1<n||o?d=this.eMarks[u]+1:d=this.eMarks[u];l<d&&s<r;){let f=this.src.charCodeAt(l);if(z(f))f===9?s+=4-(s+this.bsCount[u])%4:s++;else if(l-c<this.tShift[u])s++;else break;l++}s>r?i[a]=new Array(s-r+1).join(" ")+this.src.slice(l,d):i[a]=this.src.slice(l,d)}return i.join("")};Se.prototype.Token=Me;var $s=Se;var op=65536;function uo(e,t){let n=e.bMarks[t]+e.tShift[t],r=e.eMarks[t];return e.src.slice(n,r)}function Cs(e){let t=[],n=e.length,r=0,o=e.charCodeAt(r),i=!1,a=0,u="";for(;r<n;)o===124&&(i?(u+=e.substring(a,r-1),a=r):(t.push(u+e.substring(a,r)),u="",a=r+1)),i=o===92,r++,o=e.charCodeAt(r);return t.push(u+e.substring(a)),t}function so(e,t,n,r){if(t+2>n)return!1;let o=t+1;if(e.sCount[o]<e.blkIndent||e.sCount[o]-e.blkIndent>=4)return!1;let i=e.bMarks[o]+e.tShift[o];if(i>=e.eMarks[o])return!1;let a=e.src.charCodeAt(i++);if(a!==124&&a!==45&&a!==58||i>=e.eMarks[o])return!1;let u=e.src.charCodeAt(i++);if(u!==124&&u!==45&&u!==58&&!z(u)||a===45&&z(u))return!1;for(;i<e.eMarks[o];){let x=e.src.charCodeAt(i);if(x!==124&&x!==45&&x!==58&&!z(x))return!1;i++}let s=uo(e,t+1),c=s.split("|"),l=[];for(let x=0;x<c.length;x++){let A=c[x].trim();if(!A){if(x===0||x===c.length-1)continue;return!1}if(!/^:?-+:?$/.test(A))return!1;A.charCodeAt(A.length-1)===58?l.push(A.charCodeAt(0)===58?"center":"right"):A.charCodeAt(0)===58?l.push("left"):l.push("")}if(s=uo(e,t).trim(),s.indexOf("|")===-1||e.sCount[t]-e.blkIndent>=4)return!1;c=Cs(s),c.length&&c[0]===""&&c.shift(),c.length&&c[c.length-1]===""&&c.pop();let d=c.length;if(d===0||d!==l.length)return!1;if(r)return!0;let f=e.parentType;e.parentType="table";let m=e.md.block.ruler.getRules("blockquote"),p=e.push("table_open","table",1),h=[t,0];p.map=h;let b=e.push("thead_open","thead",1);b.map=[t,t+1];let E=e.push("tr_open","tr",1);E.map=[t,t+1];for(let x=0;x<c.length;x++){let A=e.push("th_open","th",1);l[x]&&(A.attrs=[["style","text-align:"+l[x]]]);let v=e.push("inline","",0);v.content=c[x].trim(),v.children=[],e.push("th_close","th",-1)}e.push("tr_close","tr",-1),e.push("thead_close","thead",-1);let g,y=0;for(o=t+2;o<n&&!(e.sCount[o]<e.blkIndent);o++){let x=!1;for(let v=0,N=m.length;v<N;v++)if(m[v](e,o,n,!0)){x=!0;break}if(x||(s=uo(e,o).trim(),!s)||e.sCount[o]-e.blkIndent>=4||(c=Cs(s),c.length&&c[0]===""&&c.shift(),c.length&&c[c.length-1]===""&&c.pop(),y+=d-c.length,y>op))break;if(o===t+2){let v=e.push("tbody_open","tbody",1);v.map=g=[t+2,0]}let A=e.push("tr_open","tr",1);A.map=[o,o+1];for(let v=0;v<d;v++){let N=e.push("td_open","td",1);l[v]&&(N.attrs=[["style","text-align:"+l[v]]]);let R=e.push("inline","",0);R.content=c[v]?c[v].trim():"",R.children=[],e.push("td_close","td",-1)}e.push("tr_close","tr",-1)}return g&&(e.push("tbody_close","tbody",-1),g[1]=o),e.push("table_close","table",-1),h[1]=o,e.parentType=f,e.line=o,!0}function co(e,t,n){if(e.sCount[t]-e.blkIndent<4)return!1;let r=t+1,o=r;for(;r<n;){if(e.isEmpty(r)){r++;continue}if(e.sCount[r]-e.blkIndent>=4){r++,o=r;continue}break}e.line=o;let i=e.push("code_block","code",0);return i.content=e.getLines(t,o,4+e.blkIndent,!1)+`
|
|
32
32
|
`,i.map=[t,e.line],!0}function lo(e,t,n,r){let o=e.bMarks[t]+e.tShift[t],i=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4||o+3>i)return!1;let a=e.src.charCodeAt(o);if(a!==126&&a!==96)return!1;let u=o;o=e.skipChars(o,a);let s=o-u;if(s<3)return!1;let c=e.src.slice(u,o),l=e.src.slice(o,i);if(a===96&&l.indexOf(String.fromCharCode(a))>=0)return!1;if(r)return!0;let d=t,f=!1;for(;d++,!(d>=n||(o=u=e.bMarks[d]+e.tShift[d],i=e.eMarks[d],o<i&&e.sCount[d]<e.blkIndent));)if(e.src.charCodeAt(o)===a&&!(e.sCount[d]-e.blkIndent>=4)&&(o=e.skipChars(o,a),!(o-u<s)&&(o=e.skipSpaces(o),!(o<i)))){f=!0;break}s=e.sCount[t],e.line=d+(f?1:0);let m=e.push("fence","code",0);return m.info=l,m.content=e.getLines(t+1,d,s,!0),m.markup=c,m.map=[t,e.line],!0}function fo(e,t,n,r){let o=e.bMarks[t]+e.tShift[t],i=e.eMarks[t],a=e.lineMax;if(e.sCount[t]-e.blkIndent>=4||e.src.charCodeAt(o)!==62)return!1;if(r)return!0;let u=[],s=[],c=[],l=[],d=e.md.block.ruler.getRules("blockquote"),f=e.parentType;e.parentType="blockquote";let m=!1,p;for(p=t;p<n;p++){let y=e.sCount[p]<e.blkIndent;if(o=e.bMarks[p]+e.tShift[p],i=e.eMarks[p],o>=i)break;if(e.src.charCodeAt(o++)===62&&!y){let A=e.sCount[p]+1,v,N;e.src.charCodeAt(o)===32?(o++,A++,N=!1,v=!0):e.src.charCodeAt(o)===9?(v=!0,(e.bsCount[p]+A)%4===3?(o++,A++,N=!1):N=!0):v=!1;let R=A;for(u.push(e.bMarks[p]),e.bMarks[p]=o;o<i;){let B=e.src.charCodeAt(o);if(z(B))B===9?R+=4-(R+e.bsCount[p]+(N?1:0))%4:R++;else break;o++}m=o>=i,s.push(e.bsCount[p]),e.bsCount[p]=e.sCount[p]+1+(v?1:0),c.push(e.sCount[p]),e.sCount[p]=R-A,l.push(e.tShift[p]),e.tShift[p]=o-e.bMarks[p];continue}if(m)break;let x=!1;for(let A=0,v=d.length;A<v;A++)if(d[A](e,p,n,!0)){x=!0;break}if(x){e.lineMax=p,e.blkIndent!==0&&(u.push(e.bMarks[p]),s.push(e.bsCount[p]),l.push(e.tShift[p]),c.push(e.sCount[p]),e.sCount[p]-=e.blkIndent);break}u.push(e.bMarks[p]),s.push(e.bsCount[p]),l.push(e.tShift[p]),c.push(e.sCount[p]),e.sCount[p]=-1}let h=e.blkIndent;e.blkIndent=0;let b=e.push("blockquote_open","blockquote",1);b.markup=">";let E=[t,0];b.map=E,e.md.block.tokenize(e,t,p);let g=e.push("blockquote_close","blockquote",-1);g.markup=">",e.lineMax=a,e.parentType=f,E[1]=e.line;for(let y=0;y<l.length;y++)e.bMarks[y+t]=u[y],e.tShift[y+t]=l[y],e.sCount[y+t]=c[y],e.bsCount[y+t]=s[y];return e.blkIndent=h,!0}function po(e,t,n,r){let o=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4)return!1;let i=e.bMarks[t]+e.tShift[t],a=e.src.charCodeAt(i++);if(a!==42&&a!==45&&a!==95)return!1;let u=1;for(;i<o;){let c=e.src.charCodeAt(i++);if(c!==a&&!z(c))return!1;c===a&&u++}if(u<3)return!1;if(r)return!0;e.line=t+1;let s=e.push("hr","hr",0);return s.map=[t,e.line],s.markup=Array(u+1).join(String.fromCharCode(a)),!0}function Ds(e,t){let n=e.eMarks[t],r=e.bMarks[t]+e.tShift[t],o=e.src.charCodeAt(r++);if(o!==42&&o!==45&&o!==43)return-1;if(r<n){let i=e.src.charCodeAt(r);if(!z(i))return-1}return r}function Ns(e,t){let n=e.bMarks[t]+e.tShift[t],r=e.eMarks[t],o=n;if(o+1>=r)return-1;let i=e.src.charCodeAt(o++);if(i<48||i>57)return-1;for(;;){if(o>=r)return-1;if(i=e.src.charCodeAt(o++),i>=48&&i<=57){if(o-n>=10)return-1;continue}if(i===41||i===46)break;return-1}return o<r&&(i=e.src.charCodeAt(o),!z(i))?-1:o}function ip(e,t){let n=e.level+2;for(let r=t+2,o=e.tokens.length-2;r<o;r++)e.tokens[r].level===n&&e.tokens[r].type==="paragraph_open"&&(e.tokens[r+2].hidden=!0,e.tokens[r].hidden=!0,r+=2)}function mo(e,t,n,r){let o,i,a,u,s=t,c=!0;if(e.sCount[s]-e.blkIndent>=4||e.listIndent>=0&&e.sCount[s]-e.listIndent>=4&&e.sCount[s]<e.blkIndent)return!1;let l=!1;r&&e.parentType==="paragraph"&&e.sCount[s]>=e.blkIndent&&(l=!0);let d,f,m;if((m=Ns(e,s))>=0){if(d=!0,a=e.bMarks[s]+e.tShift[s],f=Number(e.src.slice(a,m-1)),l&&f!==1)return!1}else if((m=Ds(e,s))>=0)d=!1;else return!1;if(l&&e.skipSpaces(m)>=e.eMarks[s])return!1;if(r)return!0;let p=e.src.charCodeAt(m-1),h=e.tokens.length;d?(u=e.push("ordered_list_open","ol",1),f!==1&&(u.attrs=[["start",f]])):u=e.push("bullet_list_open","ul",1);let b=[s,0];u.map=b,u.markup=String.fromCharCode(p);let E=!1,g=e.md.block.ruler.getRules("list"),y=e.parentType;for(e.parentType="list";s<n;){i=m,o=e.eMarks[s];let x=e.sCount[s]+m-(e.bMarks[s]+e.tShift[s]),A=x;for(;i<o;){let q=e.src.charCodeAt(i);if(q===9)A+=4-(A+e.bsCount[s])%4;else if(q===32)A++;else break;i++}let v=i,N;v>=o?N=1:N=A-x,N>4&&(N=1);let R=x+N;u=e.push("list_item_open","li",1),u.markup=String.fromCharCode(p);let B=[s,0];u.map=B,d&&(u.info=e.src.slice(a,m-1));let H=e.tight,J=e.tShift[s],ne=e.sCount[s],re=e.listIndent;if(e.listIndent=e.blkIndent,e.blkIndent=R,e.tight=!0,e.tShift[s]=v-e.bMarks[s],e.sCount[s]=A,v>=o&&e.isEmpty(s+1)?e.line=Math.min(e.line+2,n):e.md.block.tokenize(e,s,n,!0),(!e.tight||E)&&(c=!1),E=e.line-s>1&&e.isEmpty(e.line-1),e.blkIndent=e.listIndent,e.listIndent=re,e.tShift[s]=J,e.sCount[s]=ne,e.tight=H,u=e.push("list_item_close","li",-1),u.markup=String.fromCharCode(p),s=e.line,B[1]=s,s>=n||e.sCount[s]<e.blkIndent||e.sCount[s]-e.blkIndent>=4)break;let K=!1;for(let q=0,k=g.length;q<k;q++)if(g[q](e,s,n,!0)){K=!0;break}if(K)break;if(d){if(m=Ns(e,s),m<0)break;a=e.bMarks[s]+e.tShift[s]}else if(m=Ds(e,s),m<0)break;if(p!==e.src.charCodeAt(m-1))break}return d?u=e.push("ordered_list_close","ol",-1):u=e.push("bullet_list_close","ul",-1),u.markup=String.fromCharCode(p),b[1]=s,e.line=s,e.parentType=y,c&&ip(e,h),!0}function ho(e,t,n,r){let o=e.bMarks[t]+e.tShift[t],i=e.eMarks[t],a=t+1;if(e.sCount[t]-e.blkIndent>=4||e.src.charCodeAt(o)!==91)return!1;function u(g){let y=e.lineMax;if(g>=y||e.isEmpty(g))return null;let x=!1;if(e.sCount[g]-e.blkIndent>3&&(x=!0),e.sCount[g]<0&&(x=!0),!x){let N=e.md.block.ruler.getRules("reference"),R=e.parentType;e.parentType="reference";let B=!1;for(let H=0,J=N.length;H<J;H++)if(N[H](e,g,y,!0)){B=!0;break}if(e.parentType=R,B)return null}let A=e.bMarks[g]+e.tShift[g],v=e.eMarks[g];return e.src.slice(A,v+1)}let s=e.src.slice(o,i+1);i=s.length;let c=-1;for(o=1;o<i;o++){let g=s.charCodeAt(o);if(g===91)return!1;if(g===93){c=o;break}else if(g===10){let y=u(a);y!==null&&(s+=y,i=s.length,a++)}else if(g===92&&(o++,o<i&&s.charCodeAt(o)===10)){let y=u(a);y!==null&&(s+=y,i=s.length,a++)}}if(c<0||s.charCodeAt(c+1)!==58)return!1;for(o=c+2;o<i;o++){let g=s.charCodeAt(o);if(g===10){let y=u(a);y!==null&&(s+=y,i=s.length,a++)}else if(!z(g))break}let l=e.md.helpers.parseLinkDestination(s,o,i);if(!l.ok)return!1;let d=e.md.normalizeLink(l.str);if(!e.md.validateLink(d))return!1;o=l.pos;let f=o,m=a,p=o;for(;o<i;o++){let g=s.charCodeAt(o);if(g===10){let y=u(a);y!==null&&(s+=y,i=s.length,a++)}else if(!z(g))break}let h=e.md.helpers.parseLinkTitle(s,o,i);for(;h.can_continue;){let g=u(a);if(g===null)break;s+=g,o=i,i=s.length,a++,h=e.md.helpers.parseLinkTitle(s,o,i,h)}let b;for(o<i&&p!==o&&h.ok?(b=h.str,o=h.pos):(b="",o=f,a=m);o<i;){let g=s.charCodeAt(o);if(!z(g))break;o++}if(o<i&&s.charCodeAt(o)!==10&&b)for(b="",o=f,a=m;o<i;){let g=s.charCodeAt(o);if(!z(g))break;o++}if(o<i&&s.charCodeAt(o)!==10)return!1;let E=et(s.slice(1,c));return E?(r||(typeof e.env.references>"u"&&(e.env.references={}),typeof e.env.references[E]>"u"&&(e.env.references[E]={title:b,href:d}),e.line=a),!0):!1}var Ts=["address","article","aside","base","basefont","blockquote","body","caption","center","col","colgroup","dd","details","dialog","dir","div","dl","dt","fieldset","figcaption","figure","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hr","html","iframe","legend","li","link","main","menu","menuitem","nav","noframes","ol","optgroup","option","p","param","search","section","summary","table","tbody","td","tfoot","th","thead","title","tr","track","ul"];var ap="[a-zA-Z_:][a-zA-Z0-9:._-]*",up="[^\"'=<>`\\x00-\\x20]+",sp="'[^']*'",cp='"[^"]*"',lp="(?:"+up+"|"+sp+"|"+cp+")",dp="(?:\\s+"+ap+"(?:\\s*=\\s*"+lp+")?)",Os="<[A-Za-z][A-Za-z0-9\\-]*"+dp+"*\\s*\\/?>",Rs="<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>",fp="<!---?>|<!--(?:[^-]|-[^-]|--[^>])*-->",pp="<[?][\\s\\S]*?[?]>",mp="<![A-Za-z][^>]*>",hp="<!\\[CDATA\\[[\\s\\S]*?\\]\\]>",Ms=new RegExp("^(?:"+Os+"|"+Rs+"|"+fp+"|"+pp+"|"+mp+"|"+hp+")"),Is=new RegExp("^(?:"+Os+"|"+Rs+")");var rt=[[/^<(script|pre|style|textarea)(?=(\s|>|$))/i,/<\/(script|pre|style|textarea)>/i,!0],[/^<!--/,/-->/,!0],[/^<\?/,/\?>/,!0],[/^<![A-Za-z]/,/>/,!0],[/^<!\[CDATA\[/,/\]\]>/,!0],[new RegExp("^</?("+Ts.join("|")+")(?=(\\s|/?>|$))","i"),/^$/,!0],[new RegExp(Is.source+"\\s*$"),/^$/,!1]];function bo(e,t,n,r){let o=e.bMarks[t]+e.tShift[t],i=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4||!e.md.options.html||e.src.charCodeAt(o)!==60)return!1;let a=e.src.slice(o,i),u=0;for(;u<rt.length&&!rt[u][0].test(a);u++);if(u===rt.length)return!1;if(r)return rt[u][2];let s=t+1,c=rt[u][1].test("");if(!rt[u][1].test(a)){for(;s<n&&!(e.sCount[s]<e.blkIndent&&(c||!e.isEmpty(s)));s++)if(o=e.bMarks[s]+e.tShift[s],i=e.eMarks[s],a=e.src.slice(o,i),rt[u][1].test(a)){a.length!==0&&s++;break}}e.line=s;let l=e.push("html_block","",0);return l.map=[t,s],l.content=e.getLines(t,s,e.blkIndent,!0),!0}function go(e,t,n,r){let o=e.bMarks[t]+e.tShift[t],i=e.eMarks[t];if(e.sCount[t]-e.blkIndent>=4)return!1;let a=e.src.charCodeAt(o);if(a!==35||o>=i)return!1;let u=1;for(a=e.src.charCodeAt(++o);a===35&&o<i&&u<=6;)u++,a=e.src.charCodeAt(++o);if(u>6||o<i&&!z(a))return!1;if(r)return!0;i=e.skipSpacesBack(i,o);let s=e.skipCharsBack(i,35,o);s>o&&z(e.src.charCodeAt(s-1))&&(i=s),e.line=t+1;let c=e.push("heading_open","h"+String(u),1);c.markup="########".slice(0,u),c.map=[t,e.line];let l=e.push("inline","",0);l.content=tt(e.src.slice(o,i)),l.map=[t,e.line],l.children=[];let d=e.push("heading_close","h"+String(u),-1);return d.markup="########".slice(0,u),!0}function _o(e,t,n){let r=e.md.block.ruler.getRules("paragraph");if(e.sCount[t]-e.blkIndent>=4)return!1;let o=e.parentType;e.parentType="paragraph";let i=0,a,u=t+1;for(;u<n&&!e.isEmpty(u);u++){if(e.sCount[u]-e.blkIndent>3)continue;if(e.sCount[u]>=e.blkIndent){let m=e.bMarks[u]+e.tShift[u],p=e.eMarks[u];if(m<p&&(a=e.src.charCodeAt(m),(a===45||a===61)&&(m=e.skipChars(m,a),m=e.skipSpaces(m),m>=p))){i=a===61?1:2;break}}if(e.sCount[u]<0)continue;let f=!1;for(let m=0,p=r.length;m<p;m++)if(r[m](e,u,n,!0)){f=!0;break}if(f)break}if(!i)return e.parentType=o,!1;let s=tt(e.getLines(t,u,e.blkIndent,!1));e.line=u+1;let c=e.push("heading_open","h"+String(i),1);c.markup=String.fromCharCode(a),c.map=[t,e.line];let l=e.push("inline","",0);l.content=s,l.map=[t,e.line-1],l.children=[];let d=e.push("heading_close","h"+String(i),-1);return d.markup=String.fromCharCode(a),e.parentType=o,!0}function Eo(e,t,n){let r=e.md.block.ruler.getRules("paragraph"),o=e.parentType,i=t+1;for(e.parentType="paragraph";i<n&&!e.isEmpty(i);i++){if(e.sCount[i]-e.blkIndent>3||e.sCount[i]<0)continue;let c=!1;for(let l=0,d=r.length;l<d;l++)if(r[l](e,i,n,!0)){c=!0;break}if(c)break}let a=tt(e.getLines(t,i,e.blkIndent,!1));e.line=i;let u=e.push("paragraph_open","p",1);u.map=[t,e.line];let s=e.push("inline","",0);return s.content=a,s.map=[t,e.line],s.children=[],e.push("paragraph_close","p",-1),e.parentType=o,!0}var Tn=[["table",so,["paragraph","reference"]],["code",co],["fence",lo,["paragraph","reference","blockquote","list"]],["blockquote",fo,["paragraph","reference","blockquote","list"]],["hr",po,["paragraph","reference","blockquote","list"]],["list",mo,["paragraph","reference","blockquote"]],["reference",ho],["html_block",bo,["paragraph","reference","blockquote"]],["heading",go,["paragraph","reference","blockquote"]],["lheading",_o],["paragraph",Eo]];function On(){this.ruler=new nt;for(let e=0;e<Tn.length;e++)this.ruler.push(Tn[e][0],Tn[e][1],{alt:(Tn[e][2]||[]).slice()})}On.prototype.tokenize=function(e,t,n){let r=this.ruler.getRules(""),o=r.length,i=e.md.options.maxNesting,a=t,u=!1;for(;a<n&&(e.line=a=e.skipEmptyLines(a),!(a>=n||e.sCount[a]<e.blkIndent));){if(e.level>=i){e.line=n;break}let s=e.line,c=!1;for(let l=0;l<o;l++)if(c=r[l](e,a,n,!1),c){if(s>=e.line)throw new Error("block rule didn't increment state.line");break}if(!c)throw new Error("none of the block rules matched");e.tight=!u,e.isEmpty(e.line-1)&&(u=!0),a=e.line,a<n&&e.isEmpty(a)&&(u=!0,a++,e.line=a)}};On.prototype.parse=function(e,t,n,r){if(!e)return;let o=new this.State(e,t,n,r);this.tokenize(o,o.line,o.lineMax)};On.prototype.State=$s;var Ls=On;function zt(e,t,n,r){this.src=e,this.env=n,this.md=t,this.tokens=r,this.tokens_meta=Array(r.length),this.pos=0,this.posMax=this.src.length,this.level=0,this.pending="",this.pendingLevel=0,this.cache={},this.delimiters=[],this._prev_delimiters=[],this.backticks={},this.backticksScanned=!1,this.linkLevel=0}zt.prototype.pushPending=function(){let e=new Me("text","",0);return e.content=this.pending,e.level=this.pendingLevel,this.tokens.push(e),this.pending="",e};zt.prototype.push=function(e,t,n){this.pending&&this.pushPending();let r=new Me(e,t,n),o=null;return n<0&&(this.level--,this.delimiters=this._prev_delimiters.pop()),r.level=this.level,n>0&&(this.level++,this._prev_delimiters.push(this.delimiters),this.delimiters=[],o={delimiters:this.delimiters}),this.pendingLevel=this.level,this.tokens.push(r),this.tokens_meta.push(o),r};zt.prototype.scanDelims=function(e,t){let n=this.posMax,r=this.src.charCodeAt(e),o;if(e===0)o=32;else if(e===1)o=this.src.charCodeAt(0),(o&63488)===55296&&(o=65533);else if(o=this.src.charCodeAt(e-1),(o&64512)===56320){let b=this.src.charCodeAt(e-2);o=(b&64512)===55296?65536+(b-55296<<10)+(o-56320):65533}else(o&64512)===55296&&(o=65533);let i=e;for(;i<n&&this.src.charCodeAt(i)===r;)i++;let a=i-e,u=i<n?this.src.charCodeAt(i):32;if((u&64512)===55296){let b=this.src.charCodeAt(i+1);u=(b&64512)===56320?65536+(u-55296<<10)+(b-56320):65533}else(u&64512)===56320&&(u=65533);let s=Qe(o)||Je(o),c=Qe(u)||Je(u),l=Xe(o),d=Xe(u),f=!d&&(!c||l||s),m=!l&&(!s||d||c);return{can_open:f&&(t||!m||s),can_close:m&&(t||!f||c),length:a}};zt.prototype.Token=Me;var Fs=zt;function bp(e){switch(e){case 10:case 33:case 35:case 36:case 37:case 38:case 42:case 43:case 45:case 58:case 60:case 61:case 62:case 64:case 91:case 92:case 93:case 94:case 95:case 96:case 123:case 125:case 126:return!0;default:return!1}}function yo(e,t){let n=e.pos;for(;n<e.posMax&&!bp(e.src.charCodeAt(n));)n++;return n===e.pos?!1:(t||(e.pending+=e.src.slice(e.pos,n)),e.pos=n,!0)}function gp(e){return e>=65&&e<=90||e>=97&&e<=122}function _p(e){return e>=65&&e<=90||e>=97&&e<=122||e>=48&&e<=57||e===43||e===45||e===46}function wo(e,t){if(!e.md.options.linkify||e.linkLevel>0)return!1;let n=e.pos,r=e.posMax;if(n+3>r||e.src.charCodeAt(n)!==58||e.src.charCodeAt(n+1)!==47||e.src.charCodeAt(n+2)!==47)return!1;let o=n-Math.min(10,e.pending.length,n),i=n;for(;i>o&&_p(e.src.charCodeAt(i-1));)i--;if(i===n||!gp(e.src.charCodeAt(i)))return!1;let a=n-i,u=e.md.linkify.matchAtStart(e.src.slice(i));if(!u)return!1;let s=u.url;if(s.length<=a)return!1;let c=s.length;for(;c>0&&s.charCodeAt(c-1)===42;)c--;c!==s.length&&(s=s.slice(0,c));let l=e.md.normalizeLink(s);if(!e.md.validateLink(l))return!1;if(!t){e.pending=e.pending.slice(0,-a);let d=e.push("link_open","a",1);d.attrs=[["href",l]],d.markup="linkify",d.info="auto";let f=e.push("text","",0);f.content=e.md.normalizeLinkText(s);let m=e.push("link_close","a",-1);m.markup="linkify",m.info="auto"}return e.pos+=s.length-a,!0}function ko(e,t){let n=e.pos;if(e.src.charCodeAt(n)!==10)return!1;let r=e.pending.length-1,o=e.posMax;if(!t)if(r>=0&&e.pending.charCodeAt(r)===32)if(r>=1&&e.pending.charCodeAt(r-1)===32){let i=r-1;for(;i>=1&&e.pending.charCodeAt(i-1)===32;)i--;e.pending=e.pending.slice(0,i),e.push("hardbreak","br",0)}else e.pending=e.pending.slice(0,-1),e.push("softbreak","br",0);else e.push("softbreak","br",0);for(n++;n<o&&z(e.src.charCodeAt(n));)n++;return e.pos=n,!0}var Ao=[];for(let e=0;e<256;e++)Ao.push(0);"\\!\"#$%&'()*+,./:;<=>?@[]^_`{|}~-".split("").forEach(function(e){Ao[e.charCodeAt(0)]=1});function xo(e,t){let n=e.pos,r=e.posMax;if(e.src.charCodeAt(n)!==92||(n++,n>=r))return!1;let o=e.src.charCodeAt(n);if(o===10){for(t||e.push("hardbreak","br",0),n++;n<r&&(o=e.src.charCodeAt(n),!!z(o));)n++;return e.pos=n,!0}if(o===32){if(!t){let u=e.push("text_special","",0);u.content="\\",u.markup="\\",u.info="escape"}return e.pos=n,!0}let i=e.src[n];if(o>=55296&&o<=56319&&n+1<r){let u=e.src.charCodeAt(n+1);u>=56320&&u<=57343&&(i+=e.src[n+1],n++)}let a="\\"+i;if(!t){let u=e.push("text_special","",0);o<256&&Ao[o]!==0?u.content=i:u.content=a,u.markup=a,u.info="escape"}return e.pos=n+1,!0}function vo(e,t){let n=e.pos;if(e.src.charCodeAt(n)!==96)return!1;let o=n;n++;let i=e.posMax;for(;n<i&&e.src.charCodeAt(n)===96;)n++;let a=e.src.slice(o,n),u=a.length;if(e.backticksScanned&&(e.backticks[u]||0)<=o)return t||(e.pending+=a),e.pos+=u,!0;let s=n,c;for(;(c=e.src.indexOf("`",s))!==-1;){for(s=c+1;s<i&&e.src.charCodeAt(s)===96;)s++;let l=s-c;if(l===u){if(!t){let d=e.push("code_inline","code",0);d.markup=a,d.content=e.src.slice(n,c).replace(/\n/g," ").replace(/^ (.+) $/,"$1")}return e.pos=s,!0}e.backticks[l]=c}return e.backticksScanned=!0,t||(e.pending+=a),e.pos+=u,!0}function Ep(e,t){let n=e.pos,r=e.src.charCodeAt(n);if(t||r!==126)return!1;let o=e.scanDelims(e.pos,!0),i=o.length,a=String.fromCharCode(r);if(i<2)return!1;let u;i%2&&(u=e.push("text","",0),u.content=a,i--);for(let s=0;s<i;s+=2)u=e.push("text","",0),u.content=a+a,e.delimiters.push({marker:r,length:0,token:e.tokens.length-1,end:-1,open:o.can_open,close:o.can_close});return e.pos+=o.length,!0}function Bs(e,t){let n,r=[],o=t.length;for(let i=0;i<o;i++){let a=t[i];if(a.marker!==126||a.end===-1)continue;let u=t[a.end];n=e.tokens[a.token],n.type="s_open",n.tag="s",n.nesting=1,n.markup="~~",n.content="",n=e.tokens[u.token],n.type="s_close",n.tag="s",n.nesting=-1,n.markup="~~",n.content="",e.tokens[u.token-1].type==="text"&&e.tokens[u.token-1].content==="~"&&r.push(u.token-1)}for(;r.length;){let i=r.pop(),a=i+1;for(;a<e.tokens.length&&e.tokens[a].type==="s_close";)a++;a--,i!==a&&(n=e.tokens[a],e.tokens[a]=e.tokens[i],e.tokens[i]=n)}}function yp(e){let t=e.tokens_meta,n=e.tokens_meta.length;Bs(e,e.delimiters);for(let r=0;r<n;r++)t[r]&&t[r].delimiters&&Bs(e,t[r].delimiters)}var So={tokenize:Ep,postProcess:yp};function wp(e,t){let n=e.pos,r=e.src.charCodeAt(n);if(t||r!==95&&r!==42)return!1;let o=e.scanDelims(e.pos,r===42);for(let i=0;i<o.length;i++){let a=e.push("text","",0);a.content=String.fromCharCode(r),e.delimiters.push({marker:r,length:o.length,token:e.tokens.length-1,end:-1,open:o.can_open,close:o.can_close})}return e.pos+=o.length,!0}function Us(e,t){let n=t.length;for(let r=n-1;r>=0;r--){let o=t[r];if(o.marker!==95&&o.marker!==42||o.end===-1)continue;let i=t[o.end],a=r>0&&t[r-1].end===o.end+1&&t[r-1].marker===o.marker&&t[r-1].token===o.token-1&&t[o.end+1].token===i.token+1,u=String.fromCharCode(o.marker),s=e.tokens[o.token];s.type=a?"strong_open":"em_open",s.tag=a?"strong":"em",s.nesting=1,s.markup=a?u+u:u,s.content="";let c=e.tokens[i.token];c.type=a?"strong_close":"em_close",c.tag=a?"strong":"em",c.nesting=-1,c.markup=a?u+u:u,c.content="",a&&(e.tokens[t[r-1].token].content="",e.tokens[t[o.end+1].token].content="",r--)}}function kp(e){let t=e.tokens_meta,n=e.tokens_meta.length;Us(e,e.delimiters);for(let r=0;r<n;r++)t[r]&&t[r].delimiters&&Us(e,t[r].delimiters)}var $o={tokenize:wp,postProcess:kp};function Co(e,t){let n,r,o,i,a="",u="",s=e.pos,c=!0;if(e.src.charCodeAt(e.pos)!==91)return!1;let l=e.pos,d=e.posMax,f=e.pos+1,m=e.md.helpers.parseLinkLabel(e,e.pos,!0);if(m<0)return!1;let p=m+1;if(p<d&&e.src.charCodeAt(p)===40){for(c=!1,p++;p<d&&(n=e.src.charCodeAt(p),!(!z(n)&&n!==10));p++);if(p>=d)return!1;if(s=p,o=e.md.helpers.parseLinkDestination(e.src,p,e.posMax),o.ok){for(a=e.md.normalizeLink(o.str),e.md.validateLink(a)?p=o.pos:a="",s=p;p<d&&(n=e.src.charCodeAt(p),!(!z(n)&&n!==10));p++);if(o=e.md.helpers.parseLinkTitle(e.src,p,e.posMax),p<d&&s!==p&&o.ok)for(u=o.str,p=o.pos;p<d&&(n=e.src.charCodeAt(p),!(!z(n)&&n!==10));p++);}(p>=d||e.src.charCodeAt(p)!==41)&&(c=!0),p++}if(c){if(typeof e.env.references>"u")return!1;if(p<d&&e.src.charCodeAt(p)===91?(s=p+1,p=e.md.helpers.parseLinkLabel(e,p),p>=0?r=e.src.slice(s,p++):p=m+1):p=m+1,r||(r=e.src.slice(f,m)),i=e.env.references[et(r)],!i)return e.pos=l,!1;a=i.href,u=i.title}if(!t){e.pos=f,e.posMax=m;let h=e.push("link_open","a",1),b=[["href",a]];h.attrs=b,u&&b.push(["title",u]),e.linkLevel++,e.md.inline.tokenize(e),e.linkLevel--,e.push("link_close","a",-1)}return e.pos=p,e.posMax=d,!0}function Do(e,t){let n,r,o,i,a,u,s,c,l="",d=e.pos,f=e.posMax;if(e.src.charCodeAt(e.pos)!==33||e.src.charCodeAt(e.pos+1)!==91)return!1;let m=e.pos+2,p=e.md.helpers.parseLinkLabel(e,e.pos+1,!1);if(p<0)return!1;if(i=p+1,i<f&&e.src.charCodeAt(i)===40){for(i++;i<f&&(n=e.src.charCodeAt(i),!(!z(n)&&n!==10));i++);if(i>=f)return!1;for(c=i,u=e.md.helpers.parseLinkDestination(e.src,i,e.posMax),u.ok&&(l=e.md.normalizeLink(u.str),e.md.validateLink(l)?i=u.pos:l=""),c=i;i<f&&(n=e.src.charCodeAt(i),!(!z(n)&&n!==10));i++);if(u=e.md.helpers.parseLinkTitle(e.src,i,e.posMax),i<f&&c!==i&&u.ok)for(s=u.str,i=u.pos;i<f&&(n=e.src.charCodeAt(i),!(!z(n)&&n!==10));i++);else s="";if(i>=f||e.src.charCodeAt(i)!==41)return e.pos=d,!1;i++}else{if(typeof e.env.references>"u")return!1;if(i<f&&e.src.charCodeAt(i)===91?(c=i+1,i=e.md.helpers.parseLinkLabel(e,i),i>=0?o=e.src.slice(c,i++):i=p+1):i=p+1,o||(o=e.src.slice(m,p)),a=e.env.references[et(o)],!a)return e.pos=d,!1;l=a.href,s=a.title}if(!t){r=e.src.slice(m,p);let h=[];e.md.inline.parse(r,e.md,e.env,h);let b=e.push("image","img",0),E=[["src",l],["alt",""]];b.attrs=E,b.children=h,b.content=r,s&&E.push(["title",s])}return e.pos=i,e.posMax=f,!0}var Ap=/^([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$/,xp=/^([a-zA-Z][a-zA-Z0-9+.-]{1,31}):([^<>\x00-\x20]*)$/;function No(e,t){let n=e.pos;if(e.src.charCodeAt(n)!==60)return!1;let r=e.pos,o=e.posMax;for(;;){if(++n>=o)return!1;let a=e.src.charCodeAt(n);if(a===60)return!1;if(a===62)break}let i=e.src.slice(r+1,n);if(xp.test(i)){let a=e.md.normalizeLink(i);if(!e.md.validateLink(a))return!1;if(!t){let u=e.push("link_open","a",1);u.attrs=[["href",a]],u.markup="autolink",u.info="auto";let s=e.push("text","",0);s.content=e.md.normalizeLinkText(i);let c=e.push("link_close","a",-1);c.markup="autolink",c.info="auto"}return e.pos+=i.length+2,!0}if(Ap.test(i)){let a=e.md.normalizeLink("mailto:"+i);if(!e.md.validateLink(a))return!1;if(!t){let u=e.push("link_open","a",1);u.attrs=[["href",a]],u.markup="autolink",u.info="auto";let s=e.push("text","",0);s.content=e.md.normalizeLinkText(i);let c=e.push("link_close","a",-1);c.markup="autolink",c.info="auto"}return e.pos+=i.length+2,!0}return!1}function vp(e){return/^<a[>\s]/i.test(e)}function Sp(e){return/^<\/a\s*>/i.test(e)}function $p(e){let t=e|32;return t>=97&&t<=122}function To(e,t){if(!e.md.options.html)return!1;let n=e.posMax,r=e.pos;if(e.src.charCodeAt(r)!==60||r+2>=n)return!1;let o=e.src.charCodeAt(r+1);if(o!==33&&o!==63&&o!==47&&!$p(o))return!1;let i=e.src.slice(r).match(Ms);if(!i)return!1;if(!t){let a=e.push("html_inline","",0);a.content=i[0],vp(a.content)&&e.linkLevel++,Sp(a.content)&&e.linkLevel--}return e.pos+=i[0].length,!0}var Cp=/^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i,Dp=/^&([a-z][a-z0-9]{1,31});/i;function Oo(e,t){let n=e.pos,r=e.posMax;if(e.src.charCodeAt(n)!==38||n+1>=r)return!1;if(e.src.charCodeAt(n+1)===35){let i=e.src.slice(n).match(Cp);if(i){if(!t){let a=i[1][0].toLowerCase()==="x"?parseInt(i[1].slice(1),16):parseInt(i[1],10),u=e.push("text_special","",0);u.content=Dn(a)?At(a):At(65533),u.markup=i[0],u.info="entity"}return e.pos+=i[0].length,!0}}else{let i=e.src.slice(n).match(Dp);if(i){let a=Pt(i[0]);if(a!==i[0]){if(!t){let u=e.push("text_special","",0);u.content=a,u.markup=i[0],u.info="entity"}return e.pos+=i[0].length,!0}}}return!1}function Ps(e){let t={},n=e.length;if(!n)return;let r=0,o=-2,i=[];for(let a=0;a<n;a++){let u=e[a];if(i.push(0),(e[r].marker!==u.marker||o!==u.token-1)&&(r=a),o=u.token,u.length=u.length||0,!u.close)continue;t.hasOwnProperty(u.marker)||(t[u.marker]=[-1,-1,-1,-1,-1,-1]);let s=t[u.marker][(u.open?3:0)+u.length%3],c=r-i[r]-1,l=c;for(;c>s;c-=i[c]+1){let d=e[c];if(d.marker===u.marker&&d.open&&d.end<0){let f=!1;if((d.close||u.open)&&(d.length+u.length)%3===0&&(d.length%3!==0||u.length%3!==0)&&(f=!0),!f){let m=c>0&&!e[c-1].open?i[c-1]+1:0;i[a]=a-c+m,i[c]=m,u.open=!1,d.end=a,d.close=!1,l=-1,o=-2;break}}}l!==-1&&(t[u.marker][(u.open?3:0)+(u.length||0)%3]=l)}}function Ro(e){let t=e.tokens_meta,n=e.tokens_meta.length;Ps(e.delimiters);for(let r=0;r<n;r++)t[r]&&t[r].delimiters&&Ps(t[r].delimiters)}function Mo(e){let t,n,r=0,o=e.tokens,i=e.tokens.length;for(t=n=0;t<i;t++)o[t].nesting<0&&r--,o[t].level=r,o[t].nesting>0&&r++,o[t].type==="text"&&t+1<i&&o[t+1].type==="text"?o[t+1].content=o[t].content+o[t+1].content:(t!==n&&(o[n]=o[t]),n++);t!==n&&(o.length=n)}var Io=[["text",yo],["linkify",wo],["newline",ko],["escape",xo],["backticks",vo],["strikethrough",So.tokenize],["emphasis",$o.tokenize],["link",Co],["image",Do],["autolink",No],["html_inline",To],["entity",Oo]],Lo=[["balance_pairs",Ro],["strikethrough",So.postProcess],["emphasis",$o.postProcess],["fragments_join",Mo]];function qt(){this.ruler=new nt;for(let e=0;e<Io.length;e++)this.ruler.push(Io[e][0],Io[e][1]);this.ruler2=new nt;for(let e=0;e<Lo.length;e++)this.ruler2.push(Lo[e][0],Lo[e][1])}qt.prototype.skipToken=function(e){let t=e.pos,n=this.ruler.getRules(""),r=n.length,o=e.md.options.maxNesting,i=e.cache;if(typeof i[t]<"u"){e.pos=i[t];return}let a=!1;if(e.level<o){for(let u=0;u<r;u++)if(e.level++,a=n[u](e,!0),e.level--,a){if(t>=e.pos)throw new Error("inline rule didn't increment state.pos");break}}else e.pos=e.posMax;a||e.pos++,i[t]=e.pos};qt.prototype.tokenize=function(e){let t=this.ruler.getRules(""),n=t.length,r=e.posMax,o=e.md.options.maxNesting;for(;e.pos<r;){let i=e.pos,a=!1;if(e.level<o){for(let u=0;u<n;u++)if(a=t[u](e,!1),a){if(i>=e.pos)throw new Error("inline rule didn't increment state.pos");break}}if(a){if(e.pos>=r)break;continue}e.pending+=e.src[e.pos++]}e.pending&&e.pushPending()};qt.prototype.parse=function(e,t,n,r){let o=new this.State(e,t,n,r);this.tokenize(o);let i=this.ruler2.getRules(""),a=i.length;for(let u=0;u<a;u++)i[u](o)};qt.prototype.State=Fs;var zs=qt;function qs(e){let t={};e=e||{},t.src_Any=kn.source,t.src_Cc=An.source,t.src_Z=vn.source,t.src_P=yt.source,t.src_ZPCc=[t.src_Z,t.src_P,t.src_Cc].join("|"),t.src_ZCc=[t.src_Z,t.src_Cc].join("|");let n="[><\uFF5C]";return t.src_pseudo_letter=`(?:(?!${n}|${t.src_ZPCc})${t.src_Any})`,t.src_ip4="(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)",t.src_auth=`(?:(?:(?!${t.src_ZCc}|[@/\\[\\]()]).){1,50}@)?`,t.src_port="(?::(?:6(?:[0-4]\\d{3}|5(?:[0-4]\\d{2}|5(?:[0-2]\\d|3[0-5])))|[1-5]?\\d{1,4}))?",t.src_host_terminator=`(?=$|${n}|${t.src_ZPCc})(?!${e["---"]?"-(?!--)|":"-|"}_|:\\d|\\.-|\\.(?!$|${t.src_ZPCc}))`,t.src_path=`(?:[/?#](?:(?!${t.src_ZCc}|${n}|[()[\\]{}.,"'?!\\-;]).|\\[(?:(?!${t.src_ZCc}|\\]).)*\\]|\\((?:(?!${t.src_ZCc}|[)]).)*\\)|\\{(?:(?!${t.src_ZCc}|[}]).)*\\}|\\"(?:(?!${t.src_ZCc}|["]).)+\\"|\\'(?:(?!${t.src_ZCc}|[']).)+\\'|\\'(?=${t.src_pseudo_letter}|[-])|\\.{2,}[a-zA-Z0-9%/&]|\\.(?!${t.src_ZCc}|[.]|$)|`+(e["---"]?"\\-(?!--(?:[^-]|$))(?:-*)|":"\\-+|")+`,(?!${t.src_ZCc}|$)|;(?!${t.src_ZCc}|$)|\\!+(?!${t.src_ZCc}|[!]|$)|\\?(?!${t.src_ZCc}|[?]|$))+|\\/)?`,t.src_email_name='[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]{0,63}',t.src_xn="xn--[a-z0-9\\-]{1,59}",t.src_domain_root="(?:"+t.src_xn+`|${t.src_pseudo_letter}{1,63})`,t.src_domain="(?:"+t.src_xn+`|(?:${t.src_pseudo_letter})|(?:${t.src_pseudo_letter}(?:-|${t.src_pseudo_letter}){0,61}${t.src_pseudo_letter}))`,t.src_host=`(?:(?:(?:(?:${t.src_domain})\\.)*${t.src_domain}))`,t.tpl_host_fuzzy="(?:"+t.src_ip4+`|(?:(?:(?:${t.src_domain})\\.)+(?:%TLDS%)))`,t.tpl_host_no_ip_fuzzy=`(?:(?:(?:${t.src_domain})\\.)+(?:%TLDS%))`,t.src_host_strict=t.src_host+t.src_host_terminator,t.tpl_host_fuzzy_strict=t.tpl_host_fuzzy+t.src_host_terminator,t.src_host_port_strict=t.src_host+t.src_port+t.src_host_terminator,t.tpl_host_port_fuzzy_strict=t.tpl_host_fuzzy+t.src_port+t.src_host_terminator,t.tpl_host_port_no_ip_fuzzy_strict=t.tpl_host_no_ip_fuzzy+t.src_port+t.src_host_terminator,t.tpl_host_fuzzy_test=`localhost|www\\.|\\.\\d{1,3}\\.|(?:\\.(?:%TLDS%)(?:${t.src_ZPCc}|>|$))`,t.tpl_email_fuzzy=`(^|${n}|"|\\(|${t.src_ZCc})(${t.src_email_name}@${t.tpl_host_fuzzy_strict})`,t.tpl_link_fuzzy=`(^|(?![.:/\\-_@])(?:[$+<=>^\`|\uFF5C]|${t.src_ZPCc}))((?![$+<=>^\`|\uFF5C])${t.tpl_host_port_fuzzy_strict}${t.src_path})`,t.tpl_link_no_ip_fuzzy=`(^|(?![.:/\\-_@])(?:[$+<=>^\`|\uFF5C]|${t.src_ZPCc}))((?![$+<=>^\`|\uFF5C])${t.tpl_host_port_no_ip_fuzzy_strict}${t.src_path})`,t}function Fo(e){return Array.prototype.slice.call(arguments,1).forEach(function(n){n&&Object.keys(n).forEach(function(r){e[r]=n[r]})}),e}function Mn(e){return Object.prototype.toString.call(e)}function Np(e){return Mn(e)==="[object String]"}function Tp(e){return Mn(e)==="[object Object]"}function Op(e){return Mn(e)==="[object RegExp]"}function Ws(e){return Mn(e)==="[object Function]"}function Rp(e){return e.replace(/[.?*+^$[\]\\(){}|-]/g,"\\$&")}var Gs={fuzzyLink:!0,fuzzyEmail:!0,fuzzyIP:!1};function Mp(e){return Object.keys(e||{}).reduce(function(t,n){return t||Gs.hasOwnProperty(n)},!1)}var Ip={"http:":{validate:function(e,t,n){let r=e.slice(t);return n.re.http||(n.re.http=new RegExp(`^\\/\\/${n.re.src_auth}${n.re.src_host_port_strict}${n.re.src_path}`,"i")),n.re.http.test(r)?r.match(n.re.http)[0].length:0}},"https:":"http:","ftp:":"http:","//":{validate:function(e,t,n){let r=e.slice(t);return n.re.no_http||(n.re.no_http=new RegExp("^"+n.re.src_auth+`(?:localhost|(?:(?:${n.re.src_domain})\\.)+${n.re.src_domain_root})`+n.re.src_port+n.re.src_host_terminator+n.re.src_path,"i")),n.re.no_http.test(r)?t>=3&&e[t-3]===":"||t>=3&&e[t-3]==="/"?0:r.match(n.re.no_http)[0].length:0}},"mailto:":{validate:function(e,t,n){let r=e.slice(t);return n.re.mailto||(n.re.mailto=new RegExp(`^${n.re.src_email_name}@${n.re.src_host_strict}`,"i")),n.re.mailto.test(r)?r.match(n.re.mailto)[0].length:0}}},Lp="a[cdefgilmnoqrstuwxz]|b[abdefghijmnorstvwyz]|c[acdfghiklmnoruvwxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[abdefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|m[acdeghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]",Fp="biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|\u0440\u0444".split("|");function Bp(e){return function(t,n){let r=t.slice(n);return e.test(r)?r.match(e)[0].length:0}}function Hs(){return function(e,t){t.normalize(e)}}function Rn(e){let t=e.re=qs(e.__opts__),n=e.__tlds__.slice();e.onCompile(),e.__tlds_replaced__||n.push(Lp),n.push(t.src_xn),t.src_tlds=n.join("|");function r(u){return u.replace("%TLDS%",t.src_tlds)}t.email_fuzzy=RegExp(r(t.tpl_email_fuzzy),"i"),t.email_fuzzy_global=RegExp(r(t.tpl_email_fuzzy),"ig"),t.link_fuzzy=RegExp(r(t.tpl_link_fuzzy),"i"),t.link_fuzzy_global=RegExp(r(t.tpl_link_fuzzy),"ig"),t.link_no_ip_fuzzy=RegExp(r(t.tpl_link_no_ip_fuzzy),"i"),t.link_no_ip_fuzzy_global=RegExp(r(t.tpl_link_no_ip_fuzzy),"ig"),t.host_fuzzy_test=RegExp(r(t.tpl_host_fuzzy_test),"i");let o=[];e.__compiled__={};function i(u,s){throw new Error(`(LinkifyIt) Invalid schema "${u}": ${s}`)}Object.keys(e.__schemas__).forEach(function(u){let s=e.__schemas__[u];if(s===null)return;let c={validate:null,link:null};if(e.__compiled__[u]=c,Tp(s)){Op(s.validate)?c.validate=Bp(s.validate):Ws(s.validate)?c.validate=s.validate:i(u,s),Ws(s.normalize)?c.normalize=s.normalize:s.normalize?i(u,s):c.normalize=Hs();return}if(Np(s)){o.push(u);return}i(u,s)}),o.forEach(function(u){e.__compiled__[e.__schemas__[u]]&&(e.__compiled__[u].validate=e.__compiled__[e.__schemas__[u]].validate,e.__compiled__[u].normalize=e.__compiled__[e.__schemas__[u]].normalize)}),e.__compiled__[""]={validate:null,normalize:Hs()};let a=Object.keys(e.__compiled__).filter(function(u){return u.length>0&&e.__compiled__[u]}).map(Rp).join("|");e.re.schema_test=RegExp(`(^|(?!_)(?:[><\uFF5C]|${t.src_ZPCc}))(${a})`,"i"),e.re.schema_search=RegExp(`(^|(?!_)(?:[><\uFF5C]|${t.src_ZPCc}))(${a})`,"ig"),e.re.schema_at_start=RegExp(`^${e.re.schema_search.source}`,"i"),e.re.pretest=RegExp(`(${e.re.schema_test.source})|(${e.re.host_fuzzy_test.source})|@`,"i")}function Zs(e,t,n,r){let o=e.slice(n,r);this.schema=t.toLowerCase(),this.index=n,this.lastIndex=r,this.raw=o,this.text=o,this.url=o}function me(e,t){if(!(this instanceof me))return new me(e,t);t||Mp(e)&&(t=e,e={}),this.__opts__=Fo({},Gs,t),this.__schemas__=Fo({},Ip,e),this.__compiled__={},this.__tlds__=Fp,this.__tlds_replaced__=!1,this.re={},Rn(this)}me.prototype.add=function(t,n){return this.__schemas__[t]=n,Rn(this),this};me.prototype.set=function(t){return this.__opts__=Fo(this.__opts__,t),this};me.prototype.test=function(t){if(!t.length)return!1;let n,r;if(this.re.schema_test.test(t)){for(r=this.re.schema_search,r.lastIndex=0;(n=r.exec(t))!==null;)if(this.testSchemaAt(t,n[2],r.lastIndex))return!0}return!!(this.__opts__.fuzzyLink&&this.__compiled__["http:"]&&t.search(this.re.host_fuzzy_test)>=0&&t.match(this.__opts__.fuzzyIP?this.re.link_fuzzy:this.re.link_no_ip_fuzzy)!==null||this.__opts__.fuzzyEmail&&this.__compiled__["mailto:"]&&t.indexOf("@")>=0&&t.match(this.re.email_fuzzy)!==null)};me.prototype.pretest=function(t){return this.re.pretest.test(t)};me.prototype.testSchemaAt=function(t,n,r){return this.__compiled__[n.toLowerCase()]?this.__compiled__[n.toLowerCase()].validate(t,r,this):0};me.prototype.match=function(t){let n=[],r=[],o=[],i=[],a,u,s;function c(f,m){return f?m?f.index!==m.index?f.index<m.index?f:m:f.lastIndex>=m.lastIndex?f:m:f:m}if(!t.length)return null;if(this.re.schema_test.test(t))for(s=this.re.schema_search,s.lastIndex=0;(a=s.exec(t))!==null;)u=this.testSchemaAt(t,a[2],s.lastIndex),u&&r.push({schema:a[2],index:a.index+a[1].length,lastIndex:a.index+a[0].length+u});if(this.__opts__.fuzzyLink&&this.__compiled__["http:"])for(s=this.__opts__.fuzzyIP?this.re.link_fuzzy_global:this.re.link_no_ip_fuzzy_global,s.lastIndex=0;(a=s.exec(t))!==null;)o.push({schema:"",index:a.index+a[1].length,lastIndex:a.index+a[0].length});if(this.__opts__.fuzzyEmail&&this.__compiled__["mailto:"])for(s=this.re.email_fuzzy_global,s.lastIndex=0;(a=s.exec(t))!==null;)i.push({schema:"mailto:",index:a.index+a[1].length,lastIndex:a.index+a[0].length});let l=[0,0,0],d=0;for(;;){let f=[r[l[0]],i[l[1]],o[l[2]]],m=c(c(f[0],f[1]),f[2]);if(!m)break;if(m===f[0]?l[0]++:m===f[1]?l[1]++:l[2]++,m.index<d)continue;let p=new Zs(t,m.schema,m.index,m.lastIndex);this.__compiled__[p.schema].normalize(p,this),n.push(p),d=m.lastIndex}return n.length?n:null};me.prototype.matchAtStart=function(t){if(!t.length)return null;let n=this.re.schema_at_start.exec(t);if(!n)return null;let r=this.testSchemaAt(t,n[2],n[0].length);if(!r)return null;let o=new Zs(t,n[2],n.index+n[1].length,n.index+n[0].length+r);return this.__compiled__[o.schema].normalize(o,this),o};me.prototype.tlds=function(t,n){return t=Array.isArray(t)?t:[t],n?(this.__tlds__=this.__tlds__.concat(t).sort().filter(function(r,o,i){return r!==i[o-1]}).reverse(),Rn(this),this):(this.__tlds__=t.slice(),this.__tlds_replaced__=!0,Rn(this),this)};me.prototype.normalize=function(t){t.schema||(t.url=`http://${t.url}`),t.schema==="mailto:"&&!/^mailto:/i.test(t.url)&&(t.url=`mailto:${t.url}`)};me.prototype.onCompile=function(){};var Ks=me;var Up=/^xn--/,Pp=/[^\0-\x7F]/,zp=/[\x2E\u3002\uFF0E\uFF61]/g,qp={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},Bo=35,$e=Math.floor,Uo=String.fromCharCode;function ze(e){throw new RangeError(qp[e])}function Wp(e,t){let n=[],r=e.length;for(;r--;)n[r]=t(e[r]);return n}function Vs(e,t){let n=e.split("@"),r="";n.length>1&&(r=n[0]+"@",e=n[1]),e=e.replace(zp,".");let o=e.split("."),i=Wp(o,t).join(".");return r+i}function Ys(e){let t=[],n=0,r=e.length;for(;n<r;){let o=e.charCodeAt(n++);if(o>=55296&&o<=56319&&n<r){let i=e.charCodeAt(n++);(i&64512)==56320?t.push(((o&1023)<<10)+(i&1023)+65536):(t.push(o),n--)}else t.push(o)}return t}var Hp=e=>String.fromCodePoint(...e),Gp=function(e){return e>=48&&e<58?26+(e-48):e>=65&&e<91?e-65:e>=97&&e<123?e-97:36},js=function(e,t){return e+22+75*(e<26)-((t!=0)<<5)},Xs=function(e,t,n){let r=0;for(e=n?$e(e/700):e>>1,e+=$e(e/t);e>Bo*26>>1;r+=36)e=$e(e/Bo);return $e(r+(Bo+1)*e/(e+38))},Js=function(e){let t=[],n=e.length,r=0,o=128,i=72,a=e.lastIndexOf("-");a<0&&(a=0);for(let u=0;u<a;++u)e.charCodeAt(u)>=128&&ze("not-basic"),t.push(e.charCodeAt(u));for(let u=a>0?a+1:0;u<n;){let s=r;for(let l=1,d=36;;d+=36){u>=n&&ze("invalid-input");let f=Gp(e.charCodeAt(u++));f>=36&&ze("invalid-input"),f>$e((2147483647-r)/l)&&ze("overflow"),r+=f*l;let m=d<=i?1:d>=i+26?26:d-i;if(f<m)break;let p=36-m;l>$e(2147483647/p)&&ze("overflow"),l*=p}let c=t.length+1;i=Xs(r-s,c,s==0),$e(r/c)>2147483647-o&&ze("overflow"),o+=$e(r/c),r%=c,t.splice(r++,0,o)}return String.fromCodePoint(...t)},Qs=function(e){let t=[];e=Ys(e);let n=e.length,r=128,o=0,i=72;for(let s of e)s<128&&t.push(Uo(s));let a=t.length,u=a;for(a&&t.push("-");u<n;){let s=2147483647;for(let l of e)l>=r&&l<s&&(s=l);let c=u+1;s-r>$e((2147483647-o)/c)&&ze("overflow"),o+=(s-r)*c,r=s;for(let l of e)if(l<r&&++o>2147483647&&ze("overflow"),l===r){let d=o;for(let f=36;;f+=36){let m=f<=i?1:f>=i+26?26:f-i;if(d<m)break;let p=d-m,h=36-m;t.push(Uo(js(m+p%h,0))),d=$e(p/h)}t.push(Uo(js(d,0))),i=Xs(o,c,u===a),o=0,++u}++o,++r}return t.join("")},Zp=function(e){return Vs(e,function(t){return Up.test(t)?Js(t.slice(4).toLowerCase()):t})},Kp=function(e){return Vs(e,function(t){return Pp.test(t)?"xn--"+Qs(t):t})},jp={version:"2.3.1",ucs2:{decode:Ys,encode:Hp},decode:Js,encode:Qs,toASCII:Kp,toUnicode:Zp};var Po=jp;var ec={options:{html:!1,xhtmlOut:!1,breaks:!1,langPrefix:"language-",linkify:!1,typographer:!1,quotes:"\u201C\u201D\u2018\u2019",highlight:null,maxNesting:100},components:{core:{},block:{},inline:{}}};var tc={options:{html:!1,xhtmlOut:!1,breaks:!1,langPrefix:"language-",linkify:!1,typographer:!1,quotes:"\u201C\u201D\u2018\u2019",highlight:null,maxNesting:20},components:{core:{rules:["normalize","block","inline","text_join"]},block:{rules:["paragraph"]},inline:{rules:["text"],rules2:["balance_pairs","fragments_join"]}}};var nc={options:{html:!0,xhtmlOut:!0,breaks:!1,langPrefix:"language-",linkify:!1,typographer:!1,quotes:"\u201C\u201D\u2018\u2019",highlight:null,maxNesting:20},components:{core:{rules:["normalize","block","inline","text_join"]},block:{rules:["blockquote","code","fence","heading","hr","html_block","lheading","list","reference","paragraph"]},inline:{rules:["autolink","backticks","emphasis","entity","escape","html_inline","image","link","newline","text"],rules2:["balance_pairs","emphasis","fragments_join"]}}};var Vp={default:ec,zero:tc,commonmark:nc},Yp=/^(vbscript|javascript|file|data):/,Xp=/^data:image\/(gif|png|jpeg|webp);/;function Jp(e){let t=e.trim().toLowerCase();return Yp.test(t)?Xp.test(t):!0}var rc=["http:","https:","mailto:"];function Qp(e){let t=Ut(e,!0);if(t.hostname&&(!t.protocol||rc.indexOf(t.protocol)>=0))try{t.hostname=Po.toASCII(t.hostname)}catch{}return En(Et(t))}function em(e){let t=Ut(e,!0);if(t.hostname&&(!t.protocol||rc.indexOf(t.protocol)>=0))try{t.hostname=Po.toUnicode(t.hostname)}catch{}return Bt(Et(t),Bt.defaultChars+"%")}function _e(e,t){if(!(this instanceof _e))return new _e(e,t);t||Cn(e)||(t=e||{},e="default"),this.inline=new zs,this.block=new Ls,this.core=new Ss,this.renderer=new Es,this.linkify=new Ks,this.validateLink=Jp,this.normalizeLink=Qp,this.normalizeLinkText=em,this.utils=Kr,this.helpers=kt({},Xr),this.options={},this.configure(e),t&&this.set(t)}_e.prototype.set=function(e){return kt(this.options,e),this};_e.prototype.configure=function(e){let t=this;if(Cn(e)){let n=e;if(e=Vp[n],!e)throw new Error('Wrong `markdown-it` preset "'+n+'", check name')}if(!e)throw new Error("Wrong `markdown-it` preset, can't be empty");return e.options&&t.set(e.options),e.components&&Object.keys(e.components).forEach(function(n){e.components[n].rules&&t[n].ruler.enableOnly(e.components[n].rules),e.components[n].rules2&&t[n].ruler2.enableOnly(e.components[n].rules2)}),this};_e.prototype.enable=function(e,t){let n=[];Array.isArray(e)||(e=[e]),["core","block","inline"].forEach(function(o){n=n.concat(this[o].ruler.enable(e,!0))},this),n=n.concat(this.inline.ruler2.enable(e,!0));let r=e.filter(function(o){return n.indexOf(o)<0});if(r.length&&!t)throw new Error("MarkdownIt. Failed to enable unknown rule(s): "+r);return this};_e.prototype.disable=function(e,t){let n=[];Array.isArray(e)||(e=[e]),["core","block","inline"].forEach(function(o){n=n.concat(this[o].ruler.disable(e,!0))},this),n=n.concat(this.inline.ruler2.disable(e,!0));let r=e.filter(function(o){return n.indexOf(o)<0});if(r.length&&!t)throw new Error("MarkdownIt. Failed to disable unknown rule(s): "+r);return this};_e.prototype.use=function(e){let t=[this].concat(Array.prototype.slice.call(arguments,1));return e.apply(e,t),this};_e.prototype.parse=function(e,t){if(typeof e!="string")throw new Error("Input data should be a String");let n=new this.core.State(e,this,t);return this.core.process(n),n.tokens};_e.prototype.render=function(e,t){return t=t||{},this.renderer.render(this.parse(e,t),this.options,t)};_e.prototype.parseInline=function(e,t){let n=new this.core.State(e,this,t);return n.inlineMode=!0,this.core.process(n),n.tokens};_e.prototype.renderInline=function(e,t){return t=t||{},this.renderer.render(this.parseInline(e,t),this.options,t)};var In=_e;var tm=[137,80,78,71,13,10,26,10],nm="CgBI",rm=new Set(["GIF87a","GIF89a"]),om=4096,im={px:1,pt:96/72,pc:16,in:96,cm:96/2.54,mm:96/25.4,q:96/101.6};function Fn(e){return!(e instanceof Uint8Array)||e.length===0?null:am(e)??um(e)??cm(e)??lm(e)??dm(e)}function am(e){if(!mm(e,tm,0))return null;let t=8;return e.length>=16&&St(e,12,4)===nm&&(t+=12+qo(e,8)),e.length<t+16||St(e,t+4,4)!=="IHDR"?null:Ce(qo(e,t+8),qo(e,t+12))}function um(e){if(e.length<4||e[0]!==255||e[1]!==216)return null;let t=2;for(;t+1<e.length;){if(e[t]!==255)return null;let n=e[t+1];if(n===255){t+=1;continue}if(t+=2,n===1||n>=208&&n<=215)continue;if(n===217||n===218||t+1>=e.length)return null;let r=zo(e,t);if(r<2||t+r>e.length)return null;if(sm(n))return r<7?null:Ce(zo(e,t+5),zo(e,t+3));t+=r}return null}function sm(e){return e<192||e>207?!1:e!==196&&e!==200&&e!==204}function cm(e){return e.length<10||!rm.has(St(e,0,6))?null:Ce(Ln(e,6),Ln(e,8))}function lm(e){if(e.length<16||St(e,0,4)!=="RIFF"||St(e,8,4)!=="WEBP")return null;let t=St(e,12,4);if(t==="VP8 ")return e.length<30||e[23]!==157||e[24]!==1||e[25]!==42?null:Ce(Ln(e,26)&16383,Ln(e,28)&16383);if(t==="VP8L"){if(e.length<25||e[20]!==47)return null;let n=hm(e,21);return Ce((n&16383)+1,(n>>>14&16383)+1)}return t==="VP8X"?e.length<30?null:Ce(ic(e,24)+1,ic(e,27)+1):null}function dm(e){let t=pm(e);if(!/^\s*</.test(t))return null;let n=t.match(/<svg\b[^>]*>/i);if(!n)return null;let r=oc(Wo(n[0],"width")),o=oc(Wo(n[0],"height"));if(r!==null&&o!==null)return Ce(r,o);let i=fm(n[0]);return i?r!==null?Ce(r,r*i.height/i.width):o!==null?Ce(o*i.width/i.height,o):Ce(i.width,i.height):null}function fm(e){let t=Wo(e,"viewBox");if(t===null)return null;let n=t.trim().split(/[\s,]+/);if(n.length!==4)return null;let r=Number(n[2]),o=Number(n[3]);return!(r>0)||!(o>0)?null:{width:r,height:o}}function Wo(e,t){let n=e.match(new RegExp(`[\\s"']${t}\\s*=\\s*["']([^"']*)["']`,"i"));return n?n[1]:null}function oc(e){if(e===null)return null;let t=/^\s*([0-9]*\.?[0-9]+)\s*([a-z]*)\s*$/i.exec(e);if(!t)return null;let n=t[2]?im[t[2].toLowerCase()]:1;return n===void 0?null:Number(t[1])*n}function pm(e){return new TextDecoder("utf-8").decode(e.subarray(0,om))}function Ce(e,t){let n=Math.round(e),r=Math.round(t);return!Number.isFinite(n)||!Number.isFinite(r)||n<=0||r<=0?null:{width:n,height:r}}function mm(e,t,n){if(e.length<n+t.length)return!1;for(let r=0;r<t.length;r++)if(e[n+r]!==t[r])return!1;return!0}function St(e,t,n){let r="";for(let o=0;o<n;o++)r+=String.fromCharCode(e[t+o]);return r}function zo(e,t){return e[t]<<8|e[t+1]}function Ln(e,t){return e[t]|e[t+1]<<8}function qo(e,t){return e[t]*16777216+(e[t+1]<<16|e[t+2]<<8|e[t+3])}function hm(e,t){return(e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24)>>>0}function ic(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16}var Ie=new In({html:!1,highlight:Nr});Ie.use(bc);Ie.use(gc);Ie.use(dc);Ie.use(fc);Ie.use(mc);Ie.use(_c);Ie.use(pc);var De=null;function Go(e){return e?.html!==!0&&e?.html!=="true"?Ie:(De||(De=new In({html:!0,highlight:Nr}),De.use(bc),De.use(gc),De.use(dc),De.use(fc),De.use(mc),De.use(_c),De.use(pc)),De)}function lc(e,t,n=0){let r=[];e=Em(e,t,r,n);let o=(t.md??Ie).render(e,{resolveBinding:i=>Zo(i,t),wd:{ctx:t,index:n,attrs:r},headingSlugs:t.comp.headingSlugs});return r.length?o.replace(Ho,(i,a)=>r[Number(a)]?w(r[Number(a)].raw):i):o}function ac(e,t,n,r){let o=r?"its build-time value is painted once and then never updates":"it stays literal text";e.comp.warnings.push(`${e.file}:${$(e,t)}: "{ ${n} }" is reactive, but raw HTML (an attribute or an html block) cannot bind, so ${o}. Move the value into ordinary text or a markdown link/image destination (where { ${n} } does bind), or update it from a colocated .js with wd.subscribe.`)}var bm=e=>`~wd-attr-${e}~`,Ho=/~wd-attr-(\d+)~/g,gm=/[\u0000-\u0020()<>"'`\\\u007F]/g,Bn=e=>String(e).replace(gm,t=>`%${t.charCodeAt(0).toString(16).toUpperCase().padStart(2,"0")}`);function _m(e){let t=[],n=[...e.matchAll(/`+/g)];for(let r=0;r<n.length;r++)for(let o=r+1;o<n.length;o++)if(n[o][0].length===n[r][0].length){t.push([n[r].index,n[o].index+n[o][0].length]),r=o;break}return t}function Em(e,t,n,r){let o=e.split(`
|
|
33
33
|
`),i=null;for(let a=0;a<o.length;a++){let u=o[a].match(/^(```+|~~~+)/);if(i){u&&u[1][0]===i[0]&&u[1].length>=i.length&&(i=null);continue}if(u){i=u[1];continue}let s=_m(o[a]);o[a]=o[a].replace(/\]\(([^)\n]*)\)/g,(c,l,d)=>{if(s.some(([m,p])=>d>=m&&d<p))return c;let f=l.replace(/\{\s*([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)\s*\}/g,(m,p)=>{let h=Zo(p,t);if(!h)return m;if(h.kind==="static")return mt(h.text)?(hc(t,r+a,p),""):Bn(h.text);let b=h.kind==="state"?["s",h.key??"",h.path??""]:h.meta?["m",h.meta]:["i",h.path??""];return n.push({part:b,text:h.text,raw:m}),bm(n.length-1)});return f===l?c:`](${f})`})}return o.join(`
|
|
34
|
-
`)}function dc(e){e.core.ruler.push("wd_attr_bind",t=>{let n=t.env?.wd?.attrs;if(!n||!n.length)return!1;for(let r of t.tokens)for(let o of r.children??[]){let i=o.type==="link_open"?"href":o.type==="image"?"src":"";if(!i)continue;let a=o.attrGet(i);if(!a||!a.includes("~wd-attr-"))continue;let u=[],s="",c="",l=!1,d=0;Ho.lastIndex=0;let f;for(;f=Ho.exec(a);){let m=n[Number(f[1])];m&&(f.index>d&&(u.push(a.slice(d,f.index)),s+=a.slice(d,f.index),c+=a.slice(d,f.index)),u.push(m),s+=Bn(m.text),c+=m.text,m.part[0]!=="s"&&(l=!0),d=f.index+f[0].length)}u.length&&(d<a.length&&(u.push(a.slice(d)),s+=a.slice(d),c+=a.slice(d)),o.attrSet(i,mt(c)?"":s),o.attrSet(l?"data-wd-each-attr":"data-wd-attr",JSON.stringify([i,...u.map(m=>typeof m=="string"?m:m.part)])))}return!1})}var ym=[64,96,128,160,256,320,480,640,768,960,1024,1280,1440,1536,1920,2048,2560,3840],uc=new WeakMap;function fc(e){e.core.ruler.push("wd_image_variants",t=>{let n=t.env?.wd;if(!n)return!1;for(let r of t.tokens)for(let o of r.children??[]){if(o.type!=="image"||o.attrGet("data-wd-attr")||o.attrGet("data-wd-each-attr"))continue;let i=wm(o.attrGet("src")??"",n.ctx);i&&o.attrSet("srcset",i)}return!1})}function wm(e,t){let n=uc.get(t.comp);if(!n)uc.set(t.comp,n=new Map);else if(n.has(e))return n.get(e)??null;let r=km(e,t);return n.set(e,r),r}function km(e,t){if(!e||/^(?:https?:)?\/\//i.test(e)||e.startsWith("data:")||/[?#]/.test(e))return null;let n=e.lastIndexOf(".");if(n<=e.lastIndexOf("/")+1)return null;let r=e.slice(0,n),o=e.slice(n),i,a;if(r.startsWith("/__wd/media/"))a=t.context.shelfRoot,i=r.slice(12);else if(e.startsWith("/"))a=t.context.routesRoot,i=r.slice(1);else return null;let u=t.comp.reader,s=[];for(let d of ym){let f=M.join(a,`${i}@${d}${o}`);u.exists(f)&&s.push({href:`${r}@${d}${o}`,width:sc(f,u)??d})}let c=t.comp.imageVariants?.get(M.join(a,`${i}${o}`));if(c)for(let d of c){let f=`${r}@${d}${o}`;s.some(m=>m.href===f)||s.push({href:f,width:d})}if(!s.length)return null;let l=sc(M.join(a,`${i}${o}`),u);return l&&s.push({href:e,width:l}),s.sort((d,f)=>d.width-f.width),s.map(d=>`${d.href} ${d.width}w`).join(", ")}function sc(e,t){try{return Fn(t.readBinary(e))?.width??null}catch{return null}}var Am=/^<[A-Za-z][A-Za-z0-9-]*(?=[\s/>])/,xm=/\s(?:class|id)\s*=/i;function pc(e){e.core.ruler.push("wd_html_siblings",t=>{if(!t.md.options.html)return!1;let n=t.env?.wd;if(!n)return!1;for(let r of t.tokens)r.type!=="inline"||!r.children||vm(r,n,n.ctx);return!1})}function vm(e,t,n){let r=[],o=!0;for(let a of e.children){if(a.type==="softbreak"||a.type==="hardbreak"){o=!0;continue}o&&(o=!1,r.push(a.type==="html_inline"&&a.meta?.wdText===void 0&&Am.test(a.content)&&xm.test(a.content)))}let i=-1;for(let a=0;a<=r.length;a++){if(a<r.length&&r[a]){i===-1&&(i=a);continue}i!==-1&&a-i>=2&&n.comp.warnings.push(`${n.file}:${$(n,t.index+(e.map?e.map[0]:0)+i)}: ${a-i} sibling HTML block lines will render inline in one <p>; wrap them in a container (e.g. a raw <div>)`),i=-1}}function mc(e){e.core.ruler.push("wd_raw_html",t=>{let n=t.env?.wd;if(!n)return!1;for(let r of t.tokens){let o=n.index+(r.map?r.map[0]:0);if(r.type==="html_block"){r.content=cc(r.content,n.ctx,o);continue}let i=0;for(let a of r.children??[])a.type==="softbreak"||a.type==="hardbreak"?i++:a.type==="html_inline"&&a.meta?.wdText===void 0&&(a.content=cc(a.content,n.ctx,o+i))}return!1})}var Sm=/\b(?:href|src|action|formaction|xlink:href)\s*=\s*(?:"([^"]*)|'([^']*)|([^\s>"']*))$/i;function hc(e,t,n){e.comp.warnings.push(`${e.file}:${$(e,t)}: "{ ${n} }" resolves to a javascript:, data: or vbscript: URL, so the attribute is emitted empty. Use an https:, mailto: or site-relative value, or render it as text rather than a link target.`)}function cc(e,t,n){let r=/\{\s*([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*\s*(?:\|[^}]*)?)\}/g,o="",i=0,a;for(;a=r.exec(e);){o+=e.slice(i,a.index),i=a.index+a[0].length;let u=a[1].trim(),s=Zo(u,t);if(!s){o+=a[0];continue}if(s.kind==="row"){ac(t,n,u,!1),o+=a[0];continue}s.kind==="state"&&ac(t,n,u,!0);let c=Sm.exec(o),l=c?c[1]??c[2]??c[3]:"";if(c&&mt(l+s.text)){hc(t,n,u),o=o.slice(0,o.length-l.length);continue}o+=w(s.text)}return o+e.slice(i)}function bc(e){e.inline.ruler.push("wd_binding",(t,n)=>{if(t.src.charCodeAt(t.pos)!==123)return!1;let r=/^\{\s*([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*\s*(?:\|[^}]*)?)\}/.exec(t.src.slice(t.pos));if(!r)return!1;let o=t.env?.resolveBinding,i=o?o(r[1].trim()):null;if(!i)return!1;if(!n){let a=t.push("html_inline","",0);a.content=i.html,a.meta={wdText:i.text}}return t.pos+=r[0].length,!0})}function gc(e){e.core.ruler.push("wd_attrs",t=>{for(let n of t.tokens){if(n.type!=="inline"||!n.children)continue;let r=n.children;for(let o=0;o<r.length;o++){let i=r[o];if(i.type!=="text")continue;let a=/^\{([.#][^}]*)\}/.exec(i.content);if(!a)continue;let u=$m(r,o);if(u){for(let s of a[1].split(/\s+/).filter(Boolean))s[0]==="."?u.attrJoin("class",s.slice(1)):s[0]==="#"&&u.attrSet("id",s.slice(1));i.content=i.content.slice(a[0].length)}}}return!1})}function $m(e,t){let n=e[t-1];if(!n)return null;if(n.type==="image")return n;if(n.nesting!==-1)return null;let r=n.type.replace(/_close$/,"_open"),o=0;for(let i=t-1;i>=0;i--){let a=e[i];if(a.type===n.type)o++;else if(a.type===r&&(o--,o===0))return a}return null}function Cm(e){return e.trim().toLowerCase().replace(/[^\p{L}\p{N}\s_-]+/gu,"").replace(/\s/gu,"-")||"section"}function _c(e){e.core.ruler.push("wd_heading_anchors",t=>{var o;let n=(o=t.env).headingSlugs??(o.headingSlugs=new Map),r=t.tokens;for(let i=0;i<r.length;i++){if(r[i].type!=="heading_open")continue;let a="";for(let c of r[i+1].children??[])c.type==="text"||c.type==="code_inline"?a+=c.content:c.meta?.wdText&&(a+=c.meta.wdText);let u=Cm(a),s=n.get(u)??0;n.set(u,s+1),r[i].attrSet("id",s?`${u}-${s}`:u)}return!1})}function Zo(e,t){let{path:n,stages:r}=Vu(e,t),o=n.split("."),i=o[0],a=r.length?` data-wd-fmt="${w(Yu(r))}"`:"",u=l=>r.length?Ft(l,r):l;if(Ke[i]){if(!t.loopMeta)throw _(`"{ ${e} }" uses the loop meta variable "${i}" outside a @loop in ${t.file}. Move it into a loop body, or rename your value.`,{code:"WD005",file:t.file});if(t.loopItem)return{html:`<span data-wd-each-meta="${Ke[i]}"${a}></span>`,text:"",kind:"row",meta:Ke[i]}}if(t.loopItem&&i===t.loopItem){let l=o.slice(1).join(".");return{html:`<span data-wd-each${l?` data-wd-path="${w(l)}"`:""}${a}></span>`,text:"",kind:"row",path:l}}let s=we(t.scope,i);if(s.found){let l=oe(s.value,o.slice(1)),d=Or(u(l),e,t);return{html:w(d),text:d,kind:"static"}}let c=Z(i,t);if(c){t.comp.assets.runtime=!0,Bu(t,c,e);let l=oe(t.comp.state.get(c),o.slice(1)),d=o.slice(1).join("."),f=d?` data-wd-path="${w(d)}"`:"",m=Uu(u(l),e,t);return{html:`<span data-wd-bind="${w(c)}"${f}${a}>${w(m)}</span>`,text:m,kind:"state",key:c,path:d}}return null}var Dm=["contains","==","!=",">=","<=",">","<"];var wc=new RegExp(`^(.+?)\\s+(${Dm.join("|")})\\s+(.+)$`,"i"),Ec=/\s+(and|or)\s+/iy;function kc(e){let t=[],n="",r="",o=0;for(;o<e.length;){let i=e[o];if(r)n+=i,i===r&&(r=""),o++;else if(i==='"'||i==="'")r=i,n+=i,o++;else{Ec.lastIndex=o;let a=Ec.exec(e);a?(t.push(n,a[1]),n="",o+=a[0].length):(n+=i,o++)}}return t.push(n),t}function Ac(e,t,n){let r=kc(e),o=[],i=!1;for(let a=0;a<r.length;a++){if(a%2===1){o.push(r[a].toLowerCase()==="and"?"&&":"||");continue}let u=Nm(r[a].trim(),t,n);i=i||u.usesState,o.push(`(${u.expr})`)}return{body:o.join(" "),refsState:i}}function Nm(e,t,n){let r=e.match(wc);if(!r){let s=`${t}.field contains state, or ${t}.field <op> value \u2014 e.g. ${t}.price < 50`;throw _(`Malformed where-condition "${e}" in ${n.file}. Use: ${s}`,{code:"WD220",file:n.file,hint:s,example:`${t}.price < 50`})}let o=yc(r[1].trim(),t,n),i=yc(r[3].trim(),t,n),a=o.usesState||i.usesState,u=r[2].toLowerCase();return u==="contains"?{expr:`C(${o.code}, ${i.code})`,usesState:a}:{expr:`${o.code} ${u} ${i.code}`,usesState:a}}function yc(e,t,n){if(/^"[^"]*"$/.test(e)||/^'[^']*'$/.test(e))return{code:JSON.stringify(e.slice(1,-1)),usesState:!1};if(/^-?\d+(?:\.\d+)?$/.test(e))return{code:e,usesState:!1};if(["true","false","null"].includes(e))return{code:e,usesState:!1};if(!/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(e))throw _(`Unsupported operand "${e}" in @loop where (${n.file}). Use ${t}.field, a :state name, a number, or a "string".`,{code:"WD221",file:n.file});let r=e.split(".");if(r.some(a=>["constructor","prototype","__proto__"].includes(a)))throw _(`Path "${e}" is not allowed in @loop where (${n.file})`,{code:"WD222",file:n.file});if(r[0]===t)return{code:`I(${JSON.stringify(r.slice(1).join("."))})`,usesState:!1};let o=Z(r[0],n);if(!o)throw _(`@loop where references unknown name "${r[0]}" in ${n.file}. Use the loop item (${t}.field) or a declared :state.`,{code:"WD223",file:n.file});let i=r.slice(1).join(".");return{code:`S(${JSON.stringify(o)}${i?`, ${JSON.stringify(i)}`:""})`,usesState:!0}}function Wt(e,t,n,r="@loop where"){try{return!!_t(Ye(e),t,n.comp)}catch{let o=r==="@loop where"?"treating the row as excluded":"treating it as false";return console.warn(`${r} predicate "${e}" in ${n.file} could not be evaluated at build time; ${o}. Check the condition.`),!1}}function Ko(e,t,n){if(/^"[^"]*"$/.test(e)||/^'[^']*'$/.test(e))return{code:JSON.stringify(e.slice(1,-1)),state:!1,item:!1};if(/^-?\d+(?:\.\d+)?$/.test(e))return{code:e,state:!1,item:!1};if(["true","false","null"].includes(e))return{code:e,state:!1,item:!1};if(!/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(e))throw _(`Unsupported operand "${e}" in ${n} (${t.file}). Use item.field, a :state name, a number, or a "string".`,{code:"WD224",file:t.file});let r=e.split(".");if(r.some(u=>["constructor","prototype","__proto__"].includes(u)))throw _(`Path "${e}" is not allowed in ${n} (${t.file})`,{code:"WD225",file:t.file});if(t.loopItem&&r[0]===t.loopItem)return{code:`I(${JSON.stringify(r.slice(1).join("."))})`,state:!1,item:!0};let o=we(t.scope,r[0]);if(o.found){let u=JSON.stringify(oe(o.value,r.slice(1))??null);return{code:u===void 0?"null":u,state:!1,item:!1}}let i=Z(r[0],t);if(!i)throw _(`${n} references unknown name "${r[0]}" in ${t.file}. Use a loop item field, a declared :state, a number, or a "string".`,{code:"WD226",file:t.file});let a=r.slice(1).join(".");return{code:`S(${JSON.stringify(i)}${a?`, ${JSON.stringify(a)}`:""})`,state:!0,item:!1}}function jo(e,t,n='"::: \u2026 when"'){let r=kc(e),o=[],i=!1,a=!1;for(let s=0;s<r.length;s++){if(s%2===1){o.push(r[s].toLowerCase()==="and"?"&&":"||");continue}let c=r[s].trim(),l=!1;/^not\s+/i.test(c)&&(l=!0,c=c.replace(/^not\s+/i,"").trim());let d=c.match(wc),f;if(d){let m=Ko(d[1].trim(),t,n),p=Ko(d[3].trim(),t,n);i=i||m.state||p.state,a=a||m.item||p.item;let h=d[2].toLowerCase();f=h==="contains"?`C(${m.code}, ${p.code})`:`${m.code} ${h} ${p.code}`}else{let m=Ko(c,t,n);i=i||m.state,a=a||m.item,f=m.code}o.push(l?`(!(${f}))`:`(${f})`)}let u=o.join(" ");return!i&&!a?{static:!0,value:Wt(u,void 0,t,n)}:{static:!1,body:u,item:a}}function xc(e,t){let n=[],r=e.replace(/"[^"\\]*"|'[^'\\]*'/g,i=>(n.push(JSON.stringify(i.slice(1,-1))),`__WDSTR${n.length-1}__`)),o=[];if(r=r.replace(/\b(sum|avg|min|max|count)\s*\(\s*([A-Za-z_$][\w$.]*)\s*(?:,\s*([A-Za-z_$][\w$]*)\s*)?\)/g,(i,a,u,s)=>{let c=u.split(".");if(c.some(m=>["constructor","prototype","__proto__"].includes(m)))throw _(`Path "${u}" is not allowed in :computed ${a}() (${t.file})`,{code:"WD227",file:t.file});let l=Z(c[0],t);if(!l)throw _(`:computed ${a}() references unknown state "${c[0]}" in ${t.file}. Declare it with :state or :fetch first.`,{code:"WD228",file:t.file});let d=c.slice(1).join("."),f=`S(${JSON.stringify(l)}${d?`,${JSON.stringify(d)}`:""})`;return o.push(`A(${JSON.stringify(a)},${f}${s?`,${JSON.stringify(s)}`:""})`),`__WDAGG${o.length-1}__`}),/["'\\`]/.test(r))throw _(`Unsupported string syntax in :computed expression "${e}" (${t.file})`,{code:"WD229",file:t.file});if(!/^[\w$.\s+\-*/%()<>=!&|]*$/.test(r))throw _(`Unsupported syntax in :computed expression "${e}" (${t.file}). Allowed: state names, numbers, strings, + - * / % ( ), comparisons, && || !.`,{code:"WD230",file:t.file});if(/(^|[^=!<>])=(?!=)/.test(r))throw _(`Assignment is not allowed in :computed expressions ("${e}" in ${t.file})`,{code:"WD231",file:t.file});if(/[\w$)]\s*\(/.test(r))throw _(`Function calls are not allowed in :computed expressions ("${e}" in ${t.file})`,{code:"WD232",file:t.file});return r=r.replace(/[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*/g,i=>{if(/^__WDSTR\d+__$/.test(i)||/^__WDAGG\d+__$/.test(i)||["true","false","null"].includes(i))return i;let a=i.split(".");if(a.some(c=>["constructor","prototype","__proto__"].includes(c)))throw _(`Path segment "${i}" is not allowed in :computed expressions (${t.file})`,{code:"WD233",file:t.file});let u=Z(a[0],t);if(!u)throw _(`:computed references unknown state "${a[0]}" in ${t.file}. Declare it with :state or :fetch first.`,{code:"WD234",file:t.file});let s=a.slice(1).join(".");return`S(${JSON.stringify(u)}${s?`,${JSON.stringify(s)}`:""})`}),r.replace(/__WDAGG(\d+)__/g,(i,a)=>o[Number(a)]).replace(/__WDSTR(\d+)__/g,(i,a)=>n[Number(a)])}var Cc="@loop /products.json into p where p.price < 50 sort by p.price asc",Ee=`Use: @loop src into item [where \u2026] [sort by \u2026] [reverse] [offset N] [limit N] [paginate N] [sortable] \u2014 e.g. ${Cc}`,vc='Use simpler operands \u2014 a field path, a declared :state, a plain number, or a "string".';function qn(e,t,n,r){try{return Ye(e)}catch{throw _(`${r} expression in ${S(t,n)} could not be compiled: "${e}". ${vc}`,{code:"WD190",file:t.file,line:$(t,n),hint:vc.slice(4)})}}var Dc=(e,t,n,r)=>JSON.stringify(qn(e,t,n,r)),Tm=/(^|\s)sortable(?=\s|$)/g,Om=/(^|\s)paginate\s+(\d+)(?=\s|$)/g,Rm=/(^|\s)limit\s+(\d+|[A-Za-z_$][\w$]*)$/g,Mm=/(^|\s)offset\s+(\d+|[A-Za-z_$][\w$]*)$/g,Im=/(^|\s)reverse$/g,Lm=/(^|\s)sort\s+by\s+(\{\s*[A-Za-z_$][\w$]*\s*\}|[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)(?:\s+(\{\s*[A-Za-z_$][\w$]*\s*\}|asc|desc))?$/g,Fm=/(^|\s)(sort\s+by\s|reverse(\s|$))/g;function Bm(e){let t=new Array(e.length).fill(!1),n="";for(let r=0;r<e.length;r++)n?(t[r]=!0,e[r]===n&&(n="")):(e[r]==='"'||e[r]==="'")&&(n=e[r],t[r]=!0);return t}function ot(e,t){let n=Bm(e);t.lastIndex=0;for(let r=t.exec(e);r;r=t.exec(e)){if(!n[r.index+r[1].length])return r;t.lastIndex=r.index+1}return null}function Um(e,t,n){let r=e.trim(),o=null,i=!1,a=null,u=null,s=!1,c=!1,l=null,d=()=>{throw _(`Malformed @loop clause in ${n.file}: "${e.trim()}". ${Ee}`,{code:"WD102",file:n.file})},f=ot(r,Tm);f&&(c=!0,r=(r.slice(0,f.index)+r.slice((f.index??0)+f[0].length)).replace(/\s+/g," ").trim());let m=ot(r,Om);m&&(l=Number(m[2]),l<1&&d(),r=(r.slice(0,m.index)+r.slice((m.index??0)+m[0].length)).replace(/\s+/g," ").trim());let p=ot(r,Rm);p&&(u=Sc(p[2],n),s=s||u.kind==="key",r=r.slice(0,r.length-p[0].length+p[1].length).trim()),p=ot(r,Mm),p&&(a=Sc(p[2],n),s=s||a.kind==="key",r=r.slice(0,r.length-p[0].length+p[1].length).trim()),p=ot(r,Im),p&&(i=!0,r=r.slice(0,r.length-p[0].length+p[1].length).trim()),p=ot(r,Lm),p&&(o=Pm(p[2],p[3],t,n),(o.keyKind==="key"||o.dirKind==="key")&&(s=!0),r=r.slice(0,r.length-p[0].length+p[1].length).trim());let h=null;if(r.length){let b=r.match(/^where\s+(.+)$/);if(!b)return d();h=b[1].trim(),ot(h,Fm)&&d()}return{where:h,sort:o,reverse:i,offset:a,limit:u,refsState:s,sortable:c,paginate:l}}function Pm(e,t,n,r){let o=l=>l.match(/^\{\s*([A-Za-z_$][\w$]*)\s*\}$/),i,a,u=o(e);if(u){let l=Z(u[1],r);if(!l)throw _(`@loop sort by { ${u[1]} } references unknown :state/:store in ${r.file}. ${Ee}`,{code:"WD103",file:r.file});i=l,a="key"}else{let l=e.split(".");if(l[0]!==n)throw _(`@loop sort key "${e}" must start with the loop item "${n}" in ${r.file}. ${Ee}`,{code:"WD104",file:r.file});let d=l.slice(1);if(d.some(f=>["constructor","prototype","__proto__"].includes(f)))throw _(`Sort key "${e}" is not allowed in @loop (${r.file})`,{code:"WD105",file:r.file});i=d.join("."),a="literal"}let s="asc",c="literal";if(t){let l=o(t);if(l){let d=Z(l[1],r);if(!d)throw _(`@loop sort direction { ${l[1]} } references unknown :state/:store in ${r.file}. ${Ee}`,{code:"WD106",file:r.file});s=d,c="key"}else s=t}return{key:i,keyKind:a,dir:s,dirKind:c}}function Sc(e,t){if(/^\d+$/.test(e))return{kind:"literal",value:Number(e)};let n=Z(e,t);if(!n)throw _(`@loop offset/limit "${e}" in ${t.file} is neither a non-negative integer nor a declared :state. ${Ee}`,{code:"WD107",file:t.file});return{kind:"key",value:n}}function $c(e){return e.kind==="literal"?String(e.value):`key:${e.value}`}function Vo(e,t,n,r,o,i=0){let a=e.match(/^@loop\s+(.+?)\s+into\s+([A-Za-z_$][\w$]*)(\s+.+?)?\s*$/);if(!a)throw _(`Malformed @loop in ${S(r,o)}: ${e}. ${Ee}`,{code:"WD101",file:r.file,line:$(r,o),hint:Ee.slice(5),example:Cc});let u=ee(a[1].trim()),s=a[2],c=a[3]?Um(a[3],s,r):{where:null,sort:null,reverse:!1,offset:null,limit:null,refsState:!1,sortable:!1,paginate:null},l=c.where?Ac(c.where,s,r):null;if(c.sortable&&(l||c.sort||c.reverse||c.offset||c.limit||c.paginate))throw _(`@loop sortable cannot combine with where/sort/reverse/offset/limit/paginate in ${r.file}. ${Ee}`,{code:"WD108",file:r.file});if(c.paginate&&(c.offset||c.limit))throw _(`@loop paginate cannot combine with offset/limit in ${r.file} \u2014 paginate already slices each page. ${Ee}`,{code:"WD109",file:r.file});let d={where:l,sort:c.sort,reverse:c.reverse,offset:c.offset,limit:c.limit,empty:n,emptyStart:i,clauseRefsState:c.refsState,sortable:c.sortable,paginate:c.paginate},f=Q(r,o,{kind:"loop",name:s,detail:e.replace(/^@loop\s+/,"@loop "),reactive:!!(l&&l.refsState||c.refsState)}),m={...fe(r,o+1),loopOpener:{at:S(r,o),line:e.trim()}};if(u.startsWith("/")||u.startsWith("./")||u.startsWith("../")||u.endsWith(".json")){if(d.paginate)throw Un(r);let b=mn(u,r.file,r.context,!0,S(r,o),r.comp.reader);r.comp.deps.add(b);let E=JSON.parse(r.comp.reader.readText(b));if(!Array.isArray(E))throw _(`@loop data must be a JSON array: ${b}`,{code:"WD111",file:r.file});return Pn(E,s,t,m,d)}let p=dn(u,r);if(p.found){if(d.paginate)throw Un(r);if(p.value===null||p.value===void 0)return Pn([],s,t,m,d);if(!Array.isArray(p.value))throw _(`@loop ${u} in ${S(r,o)} found an in-scope value, but it is not a list (got ${typeof p.value}). Use: a list value (e.g. \`tags: [a, b]\` in frontmatter) \u2014 or leave the field out entirely, which loops zero rows and renders the @empty branch.`,{code:"WD112",file:r.file,line:$(r,o)});return Pn(p.value,s,t,m,d)}let h=u.split(".");if(/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(u)){if(h.some(g=>["constructor","prototype","__proto__"].includes(g)))throw _(`@loop source "${u}" is not allowed in ${r.file}`,{code:"WD113",file:r.file});let b=Z(h[0],r);if(b){if(d.paginate)throw Un(r);let g=h.length>1?`${b}.${h.slice(1).join(".")}`:b;return f.reactive=!0,f.name=s,f.target=g,Rc(g,s,t,m,d)}let E=h.length===1?r.comp.collections.get(u):void 0;if(E)return r.comp.collectionsUsed.add(u),qm(E,u,s,t,m,d);if(r.loopItem&&h[0]===r.loopItem&&h.length>1){if(d.sortable)throw _(`@loop sortable is not supported on a nested (item-relative) loop in ${r.file}. ${Ee}`,{code:"WD114",file:r.file});if(d.paginate)throw Un(r);return f.reactive=!0,Jm(h.slice(1).join("."),s,t,m,d)}}throw zm(u,r)}function zm(e,t){let n=[...t.comp.collections.keys()].sort(),r=n.length?` Available collections: ${n.join(", ")}.`:"";return _(`@loop source "${e}" in ${t.file} was not found. Loop over a collection (a site/pages/<name>/ subdirectory, by its bare name), a JSON file (@loop /data.json into row), an in-scope value, or a :state list.${r}`,{code:"WD115",file:t.file})}function Un(e){return _(`@loop paginate requires a collection source (a site/pages/<name>/ subdirectory) in ${e.file}. ${Ee}`,{code:"WD110",file:e.file})}function Nc(e){if((e.reactiveDepth??0)<2)return;let t=e.loopOpener??{at:e.file,line:""};throw _(`Reactive @loop nesting is limited to one inner level in ${t.at}: "${t.line}". Unroll the outer data at build time (JSON/frontmatter source) or move the innermost list into build-time data.`,{code:"WD116",file:e.file})}function qm(e,t,n,r,o,i){if(!i.paginate)return Pn(e,n,r,o,i);let a=Yo(e,i.where,{...i,offset:null,limit:null},o),u=i.paginate,s=Math.max(1,Math.ceil(a.length/u));o.comp.pagination={perPage:u,total:s,collection:t};let l=(Wm(o)-1)*u;return Tc(a.slice(l,l+u),n,r,o,i.empty,i.emptyStart)}function Wm(e){let t=we(e.scope,"page");if(t.found&&t.value&&typeof t.value=="object"){let n=t.value.current;if(typeof n=="number"&&n>=1)return n}return 1}function Yo(e,t,n,r){let o=t?e.filter(a=>Wt(t.body,a,r)):e.slice();if(n.sort){let a=n.sort.key,u=n.sort.dir==="desc"?-1:1;o=o.map((s,c)=>({value:s,index:c})).sort((s,c)=>{let l=oe(s.value,a?a.split("."):[]),d=oe(c.value,a?a.split("."):[]),f=typeof l=="number"&&typeof d=="number"?l-d:String(l).localeCompare(String(d));return f?f*u:s.index-c.index}).map(s=>s.value)}n.reverse&&o.reverse();let i=n.offset&&n.offset.kind==="literal"?n.offset.value:0;return i&&(o=o.slice(i)),n.limit&&n.limit.kind==="literal"&&(o=o.slice(0,n.limit.value)),o}function Pn(e,t,n,r,o){if(o.sortable)throw _(`@loop sortable requires a :state or :store list to reorder, not a JSON file or in-scope value, in ${r.file}. ${Ee}`,{code:"WD117",file:r.file});return o.where&&o.where.refsState||o.clauseRefsState?Rc(null,t,n,r,{...o,data:e}):Tc(Yo(e,o.where,o,r),t,n,r,o.empty,o.emptyStart)}function Tc(e,t,n,r,o=null,i=0){if(e.length===0&&o)return r.compileBody(o,{...fe(r,i),loopMeta:!0});let a=Xo(n),u=a?[Hm(a.columns),Gm(a.columns),...n]:n,s=[],c=e.length;for(let d=0;d<c;d++){let f={$index:d,$number:d+1,$first:d===0,$last:d===c-1,$count:c},m={...a?fe(r,-2):r,loopMeta:!0,scope:Te(r.scope,{[t]:e[d],...f})};s.push(r.compileBody(u,m))}let l=Ym(s);return a?l.replace(/<thead>[\s\S]*?<\/thead>\n?/g,""):l}var Hm=e=>`|${" c |".repeat(e)}`,Gm=e=>`|${" --- |".repeat(e)}`;function Xo(e){let t=e.length;for(;t>0&&!e[t-1].trim();)t--;let n=e.slice(0,t);return!n.length||!n.every(r=>/^ {0,3}\|/.test(r))||n.some(r=>/^ {0,3}\|[\s:|-]+\|\s*$/.test(r))?null:{columns:Zm(n[0])}}function Zm(e){let t=e.trim().replace(/^\|/,"").replace(/\|$/,""),n=1;for(let r=0;r<t.length;r++)t[r]==="\\"?r++:t[r]==="|"&&n++;return n}function Oc(e,t,n){let r=e.loopOpener??{at:e.file,line:""},o=n===null?jm(t):[],i=o.map(s=>`"${s}"`).join(", "),a=o.length?` The source is static; the clauses read :state ${i}, which is what makes the loop reactive.`:"",u=o.length?`drop ${i} from the clauses so the rows unroll at build time, or build reactive rows from containers (\`::: trow\` / \`::: td\`) instead of \`|\` cells`:"a static source (a JSON file, a frontmatter list, or a collection) for a markdown table, or build reactive rows from containers (`::: trow` / `::: td`) instead of `|` cells";return _(`A reactive @loop cannot build markdown table rows in ${r.at}: "${r.line}". A reactive row is cloned into a <div>, which cannot live inside a <table>.${a} Use: ${u}.`,{code:"WD191",file:e.file,hint:u})}var Km=/\bS\("((?:[^"\\]|\\.)*)"/g;function jm(e){let t=new Set;for(let n of(e?.where?.body??"").matchAll(Km))t.add(JSON.parse(`"${n[1]}"`));for(let n of[e?.limit,e?.offset])n?.kind==="key"&&t.add(n.value);return e?.sort?.keyKind==="key"&&t.add(e.sort.key),e?.sort?.dirKind==="key"&&t.add(e.sort.dir),[...t]}var Vm=["ul","ol"];function Ym(e){if(!e.length)return"";let t=e[0];for(let n=1;n<e.length;n++)t=Xm(t,e[n]);return t}function Xm(e,t){let n=e.trimEnd(),r=t.trimStart();for(let o of Vm)if(n.endsWith(`</${o}>`)&&r.startsWith(`<${o}>`))return`${n.slice(0,-(o.length+3)).trimEnd()}
|
|
34
|
+
`)}function dc(e){e.core.ruler.push("wd_attr_bind",t=>{let n=t.env?.wd?.attrs;if(!n||!n.length)return!1;for(let r of t.tokens)for(let o of r.children??[]){let i=o.type==="link_open"?"href":o.type==="image"?"src":"";if(!i)continue;let a=o.attrGet(i);if(!a||!a.includes("~wd-attr-"))continue;let u=[],s="",c="",l=!1,d=0;Ho.lastIndex=0;let f;for(;f=Ho.exec(a);){let m=n[Number(f[1])];m&&(f.index>d&&(u.push(a.slice(d,f.index)),s+=a.slice(d,f.index),c+=a.slice(d,f.index)),u.push(m),s+=Bn(m.text),c+=m.text,m.part[0]!=="s"&&(l=!0),d=f.index+f[0].length)}u.length&&(d<a.length&&(u.push(a.slice(d)),s+=a.slice(d),c+=a.slice(d)),o.attrSet(i,mt(c)?"":s),o.attrSet(l?"data-wd-each-attr":"data-wd-attr",JSON.stringify([i,...u.map(m=>typeof m=="string"?m:m.part)])))}return!1})}var ym=[64,96,128,160,256,320,480,640,768,960,1024,1280,1440,1536,1920,2048,2560,3840],uc=new WeakMap;function fc(e){e.core.ruler.push("wd_image_variants",t=>{let n=t.env?.wd;if(!n)return!1;for(let r of t.tokens)for(let o of r.children??[]){if(o.type!=="image"||o.attrGet("data-wd-attr")||o.attrGet("data-wd-each-attr"))continue;let i=wm(o.attrGet("src")??"",n.ctx);i&&o.attrSet("srcset",i)}return!1})}function wm(e,t){let n=uc.get(t.comp);if(!n)uc.set(t.comp,n=new Map);else if(n.has(e))return n.get(e)??null;let r=km(e,t);return n.set(e,r),r}function km(e,t){if(!e||/^(?:https?:)?\/\//i.test(e)||e.startsWith("data:")||/[?#]/.test(e))return null;let n=e.lastIndexOf(".");if(n<=e.lastIndexOf("/")+1)return null;let r=e.slice(0,n),o=e.slice(n),i,a;if(r.startsWith("/__wd/media/"))a=t.context.shelfRoot,i=r.slice(12);else if(e.startsWith("/"))a=t.context.routesRoot,i=r.slice(1);else return null;let u=t.comp.reader,s=[];for(let d of ym){let f=M.join(a,`${i}@${d}${o}`);u.exists(f)&&s.push({href:`${r}@${d}${o}`,width:sc(f,u)??d})}let c=t.comp.imageVariants?.get(M.join(a,`${i}${o}`));if(c)for(let d of c){let f=`${r}@${d}${o}`;s.some(m=>m.href===f)||s.push({href:f,width:d})}if(!s.length)return null;let l=sc(M.join(a,`${i}${o}`),u);return l&&s.push({href:e,width:l}),s.sort((d,f)=>d.width-f.width),s.map(d=>`${d.href} ${d.width}w`).join(", ")}function sc(e,t){try{return Fn(t.readBinary(e))?.width??null}catch{return null}}var Am=/^<[A-Za-z][A-Za-z0-9-]*(?=[\s/>])/,xm=/\s(?:class|id)\s*=/i;function pc(e){e.core.ruler.push("wd_html_siblings",t=>{if(!t.md.options.html)return!1;let n=t.env?.wd;if(!n)return!1;for(let r of t.tokens)r.type!=="inline"||!r.children||vm(r,n,n.ctx);return!1})}function vm(e,t,n){let r=[],o=!0;for(let a of e.children){if(a.type==="softbreak"||a.type==="hardbreak"){o=!0;continue}o&&(o=!1,r.push(a.type==="html_inline"&&a.meta?.wdText===void 0&&Am.test(a.content)&&xm.test(a.content)))}let i=-1;for(let a=0;a<=r.length;a++){if(a<r.length&&r[a]){i===-1&&(i=a);continue}i!==-1&&a-i>=2&&n.comp.warnings.push(`${n.file}:${$(n,t.index+(e.map?e.map[0]:0)+i)}: ${a-i} sibling HTML block lines will render inline in one <p>; wrap them in a container (e.g. a raw <div>)`),i=-1}}function mc(e){e.core.ruler.push("wd_raw_html",t=>{let n=t.env?.wd;if(!n)return!1;for(let r of t.tokens){let o=n.index+(r.map?r.map[0]:0);if(r.type==="html_block"){r.content=cc(r.content,n.ctx,o);continue}let i=0;for(let a of r.children??[])a.type==="softbreak"||a.type==="hardbreak"?i++:a.type==="html_inline"&&a.meta?.wdText===void 0&&(a.content=cc(a.content,n.ctx,o+i))}return!1})}var Sm=/\b(?:href|src|action|formaction|xlink:href)\s*=\s*(?:"([^"]*)|'([^']*)|([^\s>"']*))$/i;function hc(e,t,n){e.comp.warnings.push(`${e.file}:${$(e,t)}: "{ ${n} }" resolves to a javascript:, data: or vbscript: URL, so the attribute is emitted empty. Use an https:, mailto: or site-relative value, or render it as text rather than a link target.`)}function cc(e,t,n){let r=/\{\s*([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*\s*(?:\|[^}]*)?)\}/g,o="",i=0,a;for(;a=r.exec(e);){o+=e.slice(i,a.index),i=a.index+a[0].length;let u=a[1].trim(),s=Zo(u,t);if(!s){o+=a[0];continue}if(s.kind==="row"){ac(t,n,u,!1),o+=a[0];continue}s.kind==="state"&&ac(t,n,u,!0);let c=Sm.exec(o),l=c?c[1]??c[2]??c[3]:"";if(c&&mt(l+s.text)){hc(t,n,u),o=o.slice(0,o.length-l.length);continue}o+=w(s.text)}return o+e.slice(i)}function bc(e){e.inline.ruler.push("wd_binding",(t,n)=>{if(t.src.charCodeAt(t.pos)!==123)return!1;let r=/^\{\s*([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*\s*(?:\|[^}]*)?)\}/.exec(t.src.slice(t.pos));if(!r)return!1;let o=t.env?.resolveBinding,i=o?o(r[1].trim()):null;if(!i)return!1;if(!n){let a=t.push("html_inline","",0);a.content=i.html,a.meta={wdText:i.text}}return t.pos+=r[0].length,!0})}function gc(e){e.core.ruler.push("wd_attrs",t=>{for(let n of t.tokens){if(n.type!=="inline"||!n.children)continue;let r=n.children;for(let o=0;o<r.length;o++){let i=r[o];if(i.type!=="text")continue;let a=/^\{((?:[.#]|sizes=")[^}]*)\}/.exec(i.content);if(!a)continue;let u=$m(r,o);if(u){for(let s of a[1].match(/sizes="[^"]*"|\S+/g)??[])s[0]==="."?u.attrJoin("class",s.slice(1)):s[0]==="#"?u.attrSet("id",s.slice(1)):u.type==="image"&&s.startsWith('sizes="')&&u.attrSet("sizes",s.slice(7,-1));i.content=i.content.slice(a[0].length)}}}return!1})}function $m(e,t){let n=e[t-1];if(!n)return null;if(n.type==="image")return n;if(n.nesting!==-1)return null;let r=n.type.replace(/_close$/,"_open"),o=0;for(let i=t-1;i>=0;i--){let a=e[i];if(a.type===n.type)o++;else if(a.type===r&&(o--,o===0))return a}return null}function Cm(e){return e.trim().toLowerCase().replace(/[^\p{L}\p{N}\s_-]+/gu,"").replace(/\s/gu,"-")||"section"}function _c(e){e.core.ruler.push("wd_heading_anchors",t=>{var o;let n=(o=t.env).headingSlugs??(o.headingSlugs=new Map),r=t.tokens;for(let i=0;i<r.length;i++){if(r[i].type!=="heading_open")continue;let a="";for(let c of r[i+1].children??[])c.type==="text"||c.type==="code_inline"?a+=c.content:c.meta?.wdText&&(a+=c.meta.wdText);let u=Cm(a),s=n.get(u)??0;n.set(u,s+1),r[i].attrSet("id",s?`${u}-${s}`:u)}return!1})}function Zo(e,t){let{path:n,stages:r}=Vu(e,t),o=n.split("."),i=o[0],a=r.length?` data-wd-fmt="${w(Yu(r))}"`:"",u=l=>r.length?Ft(l,r):l;if(Ke[i]){if(!t.loopMeta)throw _(`"{ ${e} }" uses the loop meta variable "${i}" outside a @loop in ${t.file}. Move it into a loop body, or rename your value.`,{code:"WD005",file:t.file});if(t.loopItem)return{html:`<span data-wd-each-meta="${Ke[i]}"${a}></span>`,text:"",kind:"row",meta:Ke[i]}}if(t.loopItem&&i===t.loopItem){let l=o.slice(1).join(".");return{html:`<span data-wd-each${l?` data-wd-path="${w(l)}"`:""}${a}></span>`,text:"",kind:"row",path:l}}let s=we(t.scope,i);if(s.found){let l=oe(s.value,o.slice(1)),d=Or(u(l),e,t);return{html:w(d),text:d,kind:"static"}}let c=Z(i,t);if(c){t.comp.assets.runtime=!0,Bu(t,c,e);let l=oe(t.comp.state.get(c),o.slice(1)),d=o.slice(1).join("."),f=d?` data-wd-path="${w(d)}"`:"",m=Uu(u(l),e,t);return{html:`<span data-wd-bind="${w(c)}"${f}${a}>${w(m)}</span>`,text:m,kind:"state",key:c,path:d}}return null}var Dm=["contains","==","!=",">=","<=",">","<"];var wc=new RegExp(`^(.+?)\\s+(${Dm.join("|")})\\s+(.+)$`,"i"),Ec=/\s+(and|or)\s+/iy;function kc(e){let t=[],n="",r="",o=0;for(;o<e.length;){let i=e[o];if(r)n+=i,i===r&&(r=""),o++;else if(i==='"'||i==="'")r=i,n+=i,o++;else{Ec.lastIndex=o;let a=Ec.exec(e);a?(t.push(n,a[1]),n="",o+=a[0].length):(n+=i,o++)}}return t.push(n),t}function Ac(e,t,n){let r=kc(e),o=[],i=!1;for(let a=0;a<r.length;a++){if(a%2===1){o.push(r[a].toLowerCase()==="and"?"&&":"||");continue}let u=Nm(r[a].trim(),t,n);i=i||u.usesState,o.push(`(${u.expr})`)}return{body:o.join(" "),refsState:i}}function Nm(e,t,n){let r=e.match(wc);if(!r){let s=`${t}.field contains state, or ${t}.field <op> value \u2014 e.g. ${t}.price < 50`;throw _(`Malformed where-condition "${e}" in ${n.file}. Use: ${s}`,{code:"WD220",file:n.file,hint:s,example:`${t}.price < 50`})}let o=yc(r[1].trim(),t,n),i=yc(r[3].trim(),t,n),a=o.usesState||i.usesState,u=r[2].toLowerCase();return u==="contains"?{expr:`C(${o.code}, ${i.code})`,usesState:a}:{expr:`${o.code} ${u} ${i.code}`,usesState:a}}function yc(e,t,n){if(/^"[^"]*"$/.test(e)||/^'[^']*'$/.test(e))return{code:JSON.stringify(e.slice(1,-1)),usesState:!1};if(/^-?\d+(?:\.\d+)?$/.test(e))return{code:e,usesState:!1};if(["true","false","null"].includes(e))return{code:e,usesState:!1};if(!/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(e))throw _(`Unsupported operand "${e}" in @loop where (${n.file}). Use ${t}.field, a :state name, a number, or a "string".`,{code:"WD221",file:n.file});let r=e.split(".");if(r.some(a=>["constructor","prototype","__proto__"].includes(a)))throw _(`Path "${e}" is not allowed in @loop where (${n.file})`,{code:"WD222",file:n.file});if(r[0]===t)return{code:`I(${JSON.stringify(r.slice(1).join("."))})`,usesState:!1};let o=Z(r[0],n);if(!o)throw _(`@loop where references unknown name "${r[0]}" in ${n.file}. Use the loop item (${t}.field) or a declared :state.`,{code:"WD223",file:n.file});let i=r.slice(1).join(".");return{code:`S(${JSON.stringify(o)}${i?`, ${JSON.stringify(i)}`:""})`,usesState:!0}}function Wt(e,t,n,r="@loop where"){try{return!!_t(Ye(e),t,n.comp)}catch{let o=r==="@loop where"?"treating the row as excluded":"treating it as false";return console.warn(`${r} predicate "${e}" in ${n.file} could not be evaluated at build time; ${o}. Check the condition.`),!1}}function Ko(e,t,n){if(/^"[^"]*"$/.test(e)||/^'[^']*'$/.test(e))return{code:JSON.stringify(e.slice(1,-1)),state:!1,item:!1};if(/^-?\d+(?:\.\d+)?$/.test(e))return{code:e,state:!1,item:!1};if(["true","false","null"].includes(e))return{code:e,state:!1,item:!1};if(!/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(e))throw _(`Unsupported operand "${e}" in ${n} (${t.file}). Use item.field, a :state name, a number, or a "string".`,{code:"WD224",file:t.file});let r=e.split(".");if(r.some(u=>["constructor","prototype","__proto__"].includes(u)))throw _(`Path "${e}" is not allowed in ${n} (${t.file})`,{code:"WD225",file:t.file});if(t.loopItem&&r[0]===t.loopItem)return{code:`I(${JSON.stringify(r.slice(1).join("."))})`,state:!1,item:!0};let o=we(t.scope,r[0]);if(o.found){let u=JSON.stringify(oe(o.value,r.slice(1))??null);return{code:u===void 0?"null":u,state:!1,item:!1}}let i=Z(r[0],t);if(!i)throw _(`${n} references unknown name "${r[0]}" in ${t.file}. Use a loop item field, a declared :state, a number, or a "string".`,{code:"WD226",file:t.file});let a=r.slice(1).join(".");return{code:`S(${JSON.stringify(i)}${a?`, ${JSON.stringify(a)}`:""})`,state:!0,item:!1}}function jo(e,t,n='"::: \u2026 when"'){let r=kc(e),o=[],i=!1,a=!1;for(let s=0;s<r.length;s++){if(s%2===1){o.push(r[s].toLowerCase()==="and"?"&&":"||");continue}let c=r[s].trim(),l=!1;/^not\s+/i.test(c)&&(l=!0,c=c.replace(/^not\s+/i,"").trim());let d=c.match(wc),f;if(d){let m=Ko(d[1].trim(),t,n),p=Ko(d[3].trim(),t,n);i=i||m.state||p.state,a=a||m.item||p.item;let h=d[2].toLowerCase();f=h==="contains"?`C(${m.code}, ${p.code})`:`${m.code} ${h} ${p.code}`}else{let m=Ko(c,t,n);i=i||m.state,a=a||m.item,f=m.code}o.push(l?`(!(${f}))`:`(${f})`)}let u=o.join(" ");return!i&&!a?{static:!0,value:Wt(u,void 0,t,n)}:{static:!1,body:u,item:a}}function xc(e,t){let n=[],r=e.replace(/"[^"\\]*"|'[^'\\]*'/g,i=>(n.push(JSON.stringify(i.slice(1,-1))),`__WDSTR${n.length-1}__`)),o=[];if(r=r.replace(/\b(sum|avg|min|max|count)\s*\(\s*([A-Za-z_$][\w$.]*)\s*(?:,\s*([A-Za-z_$][\w$]*)\s*)?\)/g,(i,a,u,s)=>{let c=u.split(".");if(c.some(m=>["constructor","prototype","__proto__"].includes(m)))throw _(`Path "${u}" is not allowed in :computed ${a}() (${t.file})`,{code:"WD227",file:t.file});let l=Z(c[0],t);if(!l)throw _(`:computed ${a}() references unknown state "${c[0]}" in ${t.file}. Declare it with :state or :fetch first.`,{code:"WD228",file:t.file});let d=c.slice(1).join("."),f=`S(${JSON.stringify(l)}${d?`,${JSON.stringify(d)}`:""})`;return o.push(`A(${JSON.stringify(a)},${f}${s?`,${JSON.stringify(s)}`:""})`),`__WDAGG${o.length-1}__`}),/["'\\`]/.test(r))throw _(`Unsupported string syntax in :computed expression "${e}" (${t.file})`,{code:"WD229",file:t.file});if(!/^[\w$.\s+\-*/%()<>=!&|]*$/.test(r))throw _(`Unsupported syntax in :computed expression "${e}" (${t.file}). Allowed: state names, numbers, strings, + - * / % ( ), comparisons, && || !.`,{code:"WD230",file:t.file});if(/(^|[^=!<>])=(?!=)/.test(r))throw _(`Assignment is not allowed in :computed expressions ("${e}" in ${t.file})`,{code:"WD231",file:t.file});if(/[\w$)]\s*\(/.test(r))throw _(`Function calls are not allowed in :computed expressions ("${e}" in ${t.file})`,{code:"WD232",file:t.file});return r=r.replace(/[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*/g,i=>{if(/^__WDSTR\d+__$/.test(i)||/^__WDAGG\d+__$/.test(i)||["true","false","null"].includes(i))return i;let a=i.split(".");if(a.some(c=>["constructor","prototype","__proto__"].includes(c)))throw _(`Path segment "${i}" is not allowed in :computed expressions (${t.file})`,{code:"WD233",file:t.file});let u=Z(a[0],t);if(!u)throw _(`:computed references unknown state "${a[0]}" in ${t.file}. Declare it with :state or :fetch first.`,{code:"WD234",file:t.file});let s=a.slice(1).join(".");return`S(${JSON.stringify(u)}${s?`,${JSON.stringify(s)}`:""})`}),r.replace(/__WDAGG(\d+)__/g,(i,a)=>o[Number(a)]).replace(/__WDSTR(\d+)__/g,(i,a)=>n[Number(a)])}var Cc="@loop /products.json into p where p.price < 50 sort by p.price asc",Ee=`Use: @loop src into item [where \u2026] [sort by \u2026] [reverse] [offset N] [limit N] [paginate N] [sortable] \u2014 e.g. ${Cc}`,vc='Use simpler operands \u2014 a field path, a declared :state, a plain number, or a "string".';function qn(e,t,n,r){try{return Ye(e)}catch{throw _(`${r} expression in ${S(t,n)} could not be compiled: "${e}". ${vc}`,{code:"WD190",file:t.file,line:$(t,n),hint:vc.slice(4)})}}var Dc=(e,t,n,r)=>JSON.stringify(qn(e,t,n,r)),Tm=/(^|\s)sortable(?=\s|$)/g,Om=/(^|\s)paginate\s+(\d+)(?=\s|$)/g,Rm=/(^|\s)limit\s+(\d+|[A-Za-z_$][\w$]*)$/g,Mm=/(^|\s)offset\s+(\d+|[A-Za-z_$][\w$]*)$/g,Im=/(^|\s)reverse$/g,Lm=/(^|\s)sort\s+by\s+(\{\s*[A-Za-z_$][\w$]*\s*\}|[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)(?:\s+(\{\s*[A-Za-z_$][\w$]*\s*\}|asc|desc))?$/g,Fm=/(^|\s)(sort\s+by\s|reverse(\s|$))/g;function Bm(e){let t=new Array(e.length).fill(!1),n="";for(let r=0;r<e.length;r++)n?(t[r]=!0,e[r]===n&&(n="")):(e[r]==='"'||e[r]==="'")&&(n=e[r],t[r]=!0);return t}function ot(e,t){let n=Bm(e);t.lastIndex=0;for(let r=t.exec(e);r;r=t.exec(e)){if(!n[r.index+r[1].length])return r;t.lastIndex=r.index+1}return null}function Um(e,t,n){let r=e.trim(),o=null,i=!1,a=null,u=null,s=!1,c=!1,l=null,d=()=>{throw _(`Malformed @loop clause in ${n.file}: "${e.trim()}". ${Ee}`,{code:"WD102",file:n.file})},f=ot(r,Tm);f&&(c=!0,r=(r.slice(0,f.index)+r.slice((f.index??0)+f[0].length)).replace(/\s+/g," ").trim());let m=ot(r,Om);m&&(l=Number(m[2]),l<1&&d(),r=(r.slice(0,m.index)+r.slice((m.index??0)+m[0].length)).replace(/\s+/g," ").trim());let p=ot(r,Rm);p&&(u=Sc(p[2],n),s=s||u.kind==="key",r=r.slice(0,r.length-p[0].length+p[1].length).trim()),p=ot(r,Mm),p&&(a=Sc(p[2],n),s=s||a.kind==="key",r=r.slice(0,r.length-p[0].length+p[1].length).trim()),p=ot(r,Im),p&&(i=!0,r=r.slice(0,r.length-p[0].length+p[1].length).trim()),p=ot(r,Lm),p&&(o=Pm(p[2],p[3],t,n),(o.keyKind==="key"||o.dirKind==="key")&&(s=!0),r=r.slice(0,r.length-p[0].length+p[1].length).trim());let h=null;if(r.length){let b=r.match(/^where\s+(.+)$/);if(!b)return d();h=b[1].trim(),ot(h,Fm)&&d()}return{where:h,sort:o,reverse:i,offset:a,limit:u,refsState:s,sortable:c,paginate:l}}function Pm(e,t,n,r){let o=l=>l.match(/^\{\s*([A-Za-z_$][\w$]*)\s*\}$/),i,a,u=o(e);if(u){let l=Z(u[1],r);if(!l)throw _(`@loop sort by { ${u[1]} } references unknown :state/:store in ${r.file}. ${Ee}`,{code:"WD103",file:r.file});i=l,a="key"}else{let l=e.split(".");if(l[0]!==n)throw _(`@loop sort key "${e}" must start with the loop item "${n}" in ${r.file}. ${Ee}`,{code:"WD104",file:r.file});let d=l.slice(1);if(d.some(f=>["constructor","prototype","__proto__"].includes(f)))throw _(`Sort key "${e}" is not allowed in @loop (${r.file})`,{code:"WD105",file:r.file});i=d.join("."),a="literal"}let s="asc",c="literal";if(t){let l=o(t);if(l){let d=Z(l[1],r);if(!d)throw _(`@loop sort direction { ${l[1]} } references unknown :state/:store in ${r.file}. ${Ee}`,{code:"WD106",file:r.file});s=d,c="key"}else s=t}return{key:i,keyKind:a,dir:s,dirKind:c}}function Sc(e,t){if(/^\d+$/.test(e))return{kind:"literal",value:Number(e)};let n=Z(e,t);if(!n)throw _(`@loop offset/limit "${e}" in ${t.file} is neither a non-negative integer nor a declared :state. ${Ee}`,{code:"WD107",file:t.file});return{kind:"key",value:n}}function $c(e){return e.kind==="literal"?String(e.value):`key:${e.value}`}function Vo(e,t,n,r,o,i=0){let a=e.match(/^@loop\s+(.+?)\s+into\s+([A-Za-z_$][\w$]*)(\s+.+?)?\s*$/);if(!a)throw _(`Malformed @loop in ${S(r,o)}: ${e}. ${Ee}`,{code:"WD101",file:r.file,line:$(r,o),hint:Ee.slice(5),example:Cc});let u=ee(a[1].trim()),s=a[2],c=a[3]?Um(a[3],s,r):{where:null,sort:null,reverse:!1,offset:null,limit:null,refsState:!1,sortable:!1,paginate:null},l=c.where?Ac(c.where,s,r):null;if(c.sortable&&(l||c.sort||c.reverse||c.offset||c.limit||c.paginate))throw _(`@loop sortable cannot combine with where/sort/reverse/offset/limit/paginate in ${r.file}. ${Ee}`,{code:"WD108",file:r.file});if(c.paginate&&(c.offset||c.limit))throw _(`@loop paginate cannot combine with offset/limit in ${r.file} \u2014 paginate already slices each page. ${Ee}`,{code:"WD109",file:r.file});let d={where:l,sort:c.sort,reverse:c.reverse,offset:c.offset,limit:c.limit,empty:n,emptyStart:i,clauseRefsState:c.refsState,sortable:c.sortable,paginate:c.paginate},f=Q(r,o,{kind:"loop",name:s,detail:e.replace(/^@loop\s+/,"@loop "),reactive:!!(l&&l.refsState||c.refsState)}),m={...fe(r,o+1),loopOpener:{at:S(r,o),line:e.trim()}};if(u.startsWith("/")||u.startsWith("./")||u.startsWith("../")||u.endsWith(".json")){if(d.paginate)throw Un(r);let b=mn(u,r.file,r.context,!0,S(r,o),r.comp.reader);r.comp.deps.add(b);let E=JSON.parse(r.comp.reader.readText(b));if(!Array.isArray(E))throw _(`@loop data must be a JSON array: ${b}`,{code:"WD111",file:r.file});return Pn(E,s,t,m,d)}let p=dn(u,r);if(p.found){if(d.paginate)throw Un(r);if(p.value===null||p.value===void 0)return Pn([],s,t,m,d);if(!Array.isArray(p.value))throw _(`@loop ${u} in ${S(r,o)} found an in-scope value, but it is not a list (got ${typeof p.value}). Use: a list value (e.g. \`tags: [a, b]\` in frontmatter) \u2014 or leave the field out entirely, which loops zero rows and renders the @empty branch.`,{code:"WD112",file:r.file,line:$(r,o)});return Pn(p.value,s,t,m,d)}let h=u.split(".");if(/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(u)){if(h.some(g=>["constructor","prototype","__proto__"].includes(g)))throw _(`@loop source "${u}" is not allowed in ${r.file}`,{code:"WD113",file:r.file});let b=Z(h[0],r);if(b){if(d.paginate)throw Un(r);let g=h.length>1?`${b}.${h.slice(1).join(".")}`:b;return f.reactive=!0,f.name=s,f.target=g,Rc(g,s,t,m,d)}let E=h.length===1?r.comp.collections.get(u):void 0;if(E)return r.comp.collectionsUsed.add(u),qm(E,u,s,t,m,d);if(r.loopItem&&h[0]===r.loopItem&&h.length>1){if(d.sortable)throw _(`@loop sortable is not supported on a nested (item-relative) loop in ${r.file}. ${Ee}`,{code:"WD114",file:r.file});if(d.paginate)throw Un(r);return f.reactive=!0,Jm(h.slice(1).join("."),s,t,m,d)}}throw zm(u,r)}function zm(e,t){let n=[...t.comp.collections.keys()].sort(),r=n.length?` Available collections: ${n.join(", ")}.`:"";return _(`@loop source "${e}" in ${t.file} was not found. Loop over a collection (a site/pages/<name>/ subdirectory, by its bare name), a JSON file (@loop /data.json into row), an in-scope value, or a :state list.${r}`,{code:"WD115",file:t.file})}function Un(e){return _(`@loop paginate requires a collection source (a site/pages/<name>/ subdirectory) in ${e.file}. ${Ee}`,{code:"WD110",file:e.file})}function Nc(e){if((e.reactiveDepth??0)<2)return;let t=e.loopOpener??{at:e.file,line:""};throw _(`Reactive @loop nesting is limited to one inner level in ${t.at}: "${t.line}". Unroll the outer data at build time (JSON/frontmatter source) or move the innermost list into build-time data.`,{code:"WD116",file:e.file})}function qm(e,t,n,r,o,i){if(!i.paginate)return Pn(e,n,r,o,i);let a=Yo(e,i.where,{...i,offset:null,limit:null},o),u=i.paginate,s=Math.max(1,Math.ceil(a.length/u));o.comp.pagination={perPage:u,total:s,collection:t};let l=(Wm(o)-1)*u;return Tc(a.slice(l,l+u),n,r,o,i.empty,i.emptyStart)}function Wm(e){let t=we(e.scope,"page");if(t.found&&t.value&&typeof t.value=="object"){let n=t.value.current;if(typeof n=="number"&&n>=1)return n}return 1}function Yo(e,t,n,r){let o=t?e.filter(a=>Wt(t.body,a,r)):e.slice();if(n.sort){let a=n.sort.key,u=n.sort.dir==="desc"?-1:1;o=o.map((s,c)=>({value:s,index:c})).sort((s,c)=>{let l=oe(s.value,a?a.split("."):[]),d=oe(c.value,a?a.split("."):[]),f=typeof l=="number"&&typeof d=="number"?l-d:String(l).localeCompare(String(d));return f?f*u:s.index-c.index}).map(s=>s.value)}n.reverse&&o.reverse();let i=n.offset&&n.offset.kind==="literal"?n.offset.value:0;return i&&(o=o.slice(i)),n.limit&&n.limit.kind==="literal"&&(o=o.slice(0,n.limit.value)),o}function Pn(e,t,n,r,o){if(o.sortable)throw _(`@loop sortable requires a :state or :store list to reorder, not a JSON file or in-scope value, in ${r.file}. ${Ee}`,{code:"WD117",file:r.file});return o.where&&o.where.refsState||o.clauseRefsState?Rc(null,t,n,r,{...o,data:e}):Tc(Yo(e,o.where,o,r),t,n,r,o.empty,o.emptyStart)}function Tc(e,t,n,r,o=null,i=0){if(e.length===0&&o)return r.compileBody(o,{...fe(r,i),loopMeta:!0});let a=Xo(n),u=a?[Hm(a.columns),Gm(a.columns),...n]:n,s=[],c=e.length;for(let d=0;d<c;d++){let f={$index:d,$number:d+1,$first:d===0,$last:d===c-1,$count:c},m={...a?fe(r,-2):r,loopMeta:!0,scope:Te(r.scope,{[t]:e[d],...f})};s.push(r.compileBody(u,m))}let l=Ym(s);return a?l.replace(/<thead>[\s\S]*?<\/thead>\n?/g,""):l}var Hm=e=>`|${" c |".repeat(e)}`,Gm=e=>`|${" --- |".repeat(e)}`;function Xo(e){let t=e.length;for(;t>0&&!e[t-1].trim();)t--;let n=e.slice(0,t);return!n.length||!n.every(r=>/^ {0,3}\|/.test(r))||n.some(r=>/^ {0,3}\|[\s:|-]+\|\s*$/.test(r))?null:{columns:Zm(n[0])}}function Zm(e){let t=e.trim().replace(/^\|/,"").replace(/\|$/,""),n=1;for(let r=0;r<t.length;r++)t[r]==="\\"?r++:t[r]==="|"&&n++;return n}function Oc(e,t,n){let r=e.loopOpener??{at:e.file,line:""},o=n===null?jm(t):[],i=o.map(s=>`"${s}"`).join(", "),a=o.length?` The source is static; the clauses read :state ${i}, which is what makes the loop reactive.`:"",u=o.length?`drop ${i} from the clauses so the rows unroll at build time, or build reactive rows from containers (\`::: trow\` / \`::: td\`) instead of \`|\` cells`:"a static source (a JSON file, a frontmatter list, or a collection) for a markdown table, or build reactive rows from containers (`::: trow` / `::: td`) instead of `|` cells";return _(`A reactive @loop cannot build markdown table rows in ${r.at}: "${r.line}". A reactive row is cloned into a <div>, which cannot live inside a <table>.${a} Use: ${u}.`,{code:"WD191",file:e.file,hint:u})}var Km=/\bS\("((?:[^"\\]|\\.)*)"/g;function jm(e){let t=new Set;for(let n of(e?.where?.body??"").matchAll(Km))t.add(JSON.parse(`"${n[1]}"`));for(let n of[e?.limit,e?.offset])n?.kind==="key"&&t.add(n.value);return e?.sort?.keyKind==="key"&&t.add(e.sort.key),e?.sort?.dirKind==="key"&&t.add(e.sort.dir),[...t]}var Vm=["ul","ol"];function Ym(e){if(!e.length)return"";let t=e[0];for(let n=1;n<e.length;n++)t=Xm(t,e[n]);return t}function Xm(e,t){let n=e.trimEnd(),r=t.trimStart();for(let o of Vm)if(n.endsWith(`</${o}>`)&&r.startsWith(`<${o}>`))return`${n.slice(0,-(o.length+3)).trimEnd()}
|
|
35
35
|
${r.slice(o.length+2).trimStart()}`;return Jo(e,t)??`${e}
|
|
36
36
|
${t}`}function Jo(e,t){let n=e.trimEnd(),r=t.trimStart();if(!n.endsWith("</table>")||!r.startsWith("<table>"))return null;let o=r.indexOf("<tbody>");if(o===-1)return null;let i=n.lastIndexOf("</tbody>"),a=r.slice(o+7).trimStart();return i===-1?!n.includes("<thead>")||r.includes("<thead>")?null:`${n.slice(0,n.lastIndexOf("</table>")).trimEnd()}
|
|
37
37
|
<tbody>
|
|
@@ -57,14 +57,12 @@ ${u}
|
|
|
57
57
|
`),N=o.meta.transitions===!0||o.meta.transitions==="true",R=N?`
|
|
58
58
|
<style>
|
|
59
59
|
@view-transition { navigation: auto; }
|
|
60
|
-
::view-transition-old(root) { animation: wd-nav-out
|
|
61
|
-
::view-transition-new(root) { animation: wd-nav-in
|
|
62
|
-
@keyframes wd-nav-out { to { opacity: 0;
|
|
63
|
-
@keyframes wd-nav-in { from { opacity: 0;
|
|
60
|
+
::view-transition-old(root) { animation: wd-nav-out 90ms cubic-bezier(0.4, 0, 0.2, 1) both; }
|
|
61
|
+
::view-transition-new(root) { animation: wd-nav-in 130ms cubic-bezier(0.4, 0, 0.2, 1) 80ms both; }
|
|
62
|
+
@keyframes wd-nav-out { to { opacity: 0; } }
|
|
63
|
+
@keyframes wd-nav-in { from { opacity: 0; } }
|
|
64
64
|
@media (prefers-reduced-motion: reduce) {
|
|
65
|
-
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 1ms; }
|
|
66
|
-
@keyframes wd-nav-out { to { opacity: 0; } }
|
|
67
|
-
@keyframes wd-nav-in { from { opacity: 0; } }
|
|
65
|
+
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 1ms; animation-delay: 0ms; }
|
|
68
66
|
}
|
|
69
67
|
</style>`:"",B=N?`
|
|
70
68
|
<script type="speculationrules">{"prerender":[{"where":{"and":[{"href_matches":"/*"},{"not":{"selector_matches":".no-prefetch"}},{"not":{"selector_matches":"[rel~=nofollow]"}}]},"eagerness":"moderate"}]}<\/script>`:"",H=fn(e,t,r),J=H&&H.scoped?null:Mr(o.meta,e,t,r).map(C=>It(C,t.cwd,r)).find(C=>C.scoped),ne=H&&H.scoped?H.scopeId:J?.scopeId,re=ne?pn(o.html,ne):o.html,K=rb(re,t,r),{content:q,target:k}=nb(K);return{meta:o.meta,deps:o.deps,collectionsUsed:o.collectionsUsed,symbols:o.symbols,html:`<!doctype html>
|
package/src/catalog.js
CHANGED
|
@@ -724,6 +724,8 @@ function inlineAttributesSection() {
|
|
|
724
724
|
"- Attach classes/an id to an inline element by following it with NO space:" +
|
|
725
725
|
" `[Get started](/start/){.btn}`, `{.brand}`, `*text*{.hl}`.",
|
|
726
726
|
"- Several at once: `[Go](/u/){.btn .lg #cta}`. A space before the block breaks it (stays literal).",
|
|
727
|
+
'- Images also take a quoted `sizes="…"`: `{sizes="(max-width: 640px) 100vw, 640px"}`.' +
|
|
728
|
+
" The srcset variant wiring never invents one; sizes passes through with or without a srcset.",
|
|
727
729
|
"- Works on links, images, and emphasis/strong. It does NOT work on inline `code`.",
|
|
728
730
|
""
|
|
729
731
|
];
|